diff -urN linux-2.6.30.4-orig/arch/arm/mach-pxa/datr.c linux-2.6.30.4/arch/arm/mach-pxa/datr.c --- linux-2.6.30.4-orig/arch/arm/mach-pxa/datr.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/arch/arm/mach-pxa/datr.c 2009-08-06 15:14:38.000000000 +0200 @@ -0,0 +1,447 @@ +/* + * linux/arch/arm/mach-pxa/datr.c + * + * Support for the HaslerRail DATR board. + * + * Author: Marco Hoefle + * Created: June 03, 2009 + * Copyright: HasleRail, Inc. + * e-mail: marco.hoefle@nanotronic.ch + * + * Author: Daniel Marmier + * Created: March 15, 2007 + * Copyright: HasleRail, Inc. + * e-mail: daniel.marmier@haslerrail.com + * + * based on the Phytec phyCORE-PXA270: + * + * Author: Juergen Kilb + * Created: April 05, 2005 + * Copyright: Phytec Messtechnik GmbH + * e-Mail: armlinux@phytec.de + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "generic.h" + +/* + * ABSTRACT: + * + * The PXA270 processor comes with a bunch of hardware on its silicon. + * Not all of this hardware can be used at the same time and not all + * is routed to module's connectors. Also it depends on the baseboard, what + * kind of hardware can be used in which way. + * -> So this file supports the main devices on the CPU card only! + * Refer pcm990-baseboard.c how to extend this features to get a full + * blown system with many common interfaces. + * + * The PCM-027 supports the following interfaces through its connectors and + * will be used in pcm990-baseboard.c: + * + * - LCD support + * - MMC support + * - IDE/CF card + * - FFUART + * - BTUART + * - IRUART + * - AC97 + * - SSP + * - SSP3 + * + * Claimed GPIOs: + * GPIO0 -> IRQ input from RTC + * GPIO2 -> SYS_ENA*) + * GPIO3 -> PWR_SCL + * GPIO4 -> PWR_SDA + * GPIO5 -> PowerCap0*) + * GPIO6 -> PowerCap1*) + * GPIO7 -> PowerCap2*) + * GPIO8 -> PowerCap3*) + * GPIO15 -> /CS1 + * GPIO20 -> /CS2 + * GPIO21 -> /CS3 + * GPIO33 -> /CS5 network controller select + * GPIO52 -> IRQ from network controller + * GPIO78 -> /CS2 + * GPIO80 -> /CS4 + * GPIO90 -> LED0 + * GPIO91 -> LED1 + * GPIO114 -> IRQ from CAN controller + * GPIO117 -> SCL + * GPIO118 -> SDA + * + * *) CPU internal use only + */ + +#define GPIO_ALT_FN_1_IN 0x100 +#define GPIO_ALT_FN_2_OUT 0x280 +#define GPIO18_RDY_MD (18 | GPIO_ALT_FN_1_IN) +#define GPIO49_nPWE_MD (49 | GPIO_ALT_FN_2_OUT) +#define GPIO15_nCS_1_MD (15 | GPIO_ALT_FN_2_OUT) + +#ifdef CONFIG_SMC91X +/* + * SMC91x network controller specific stuff + */ +static struct resource smc91x_resources[] __initdata = { + [0] = { + .start = DATR_ETH_PHYS + 0x300, + .end = DATR_ETH_PHYS + DATR_ETH_SIZE, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = DATR_ETH_IRQ, + .end = DATR_ETH_IRQ, + /* note: smc91x's driver doesn't use the trigger bits yet */ + .flags = IORESOURCE_IRQ | DATR_ETH_IRQ_EDGE, + } +}; + +static struct platform_device smc91x_device __initdata = { + .name = "smc91x", + .id = 0, + .num_resources = ARRAY_SIZE(smc91x_resources), + .resource = smc91x_resources, +}; +#endif + +#if defined(CONFIG_USB_ISP1760_HCD) || defined(CONFIG_USB_ISP1760_HCD_MODULE) +#include +#define ISP1761_BASE PXA_CS4_PHYS +#define ISP1761_GPIO_IRQ 91 +#define ISP1761_IRQ IRQ_GPIO(ISP1761_GPIO_IRQ) +static struct resource datr_isp1760_resources[] __initdata = { + [0] = { + .start = ISP1761_BASE, + .end = ISP1761_BASE + 0x3FFFF, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = ISP1761_IRQ, + .end = ISP1761_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct isp1760_platform_data isp1760_platform_data __initdata = { + .is_isp1761 = 0, + .bus_width_16 = 0, + .port1_otg = 0, + .analog_oc = 1, + .dack_polarity_high = 0, + .dreq_polarity_high = 0, +}; + +static struct platform_device isp1760_device __initdata = { + .name = "isp1760", + .id = 0, + .dev = { + .platform_data = &isp1760_platform_data, + }, + .num_resources = ARRAY_SIZE(datr_isp1760_resources), + .resource = datr_isp1760_resources, +}; +#endif + +/* + * NOR flash + */ +static struct physmap_flash_data datr_flash_data __initdata = { + .width = 4, +}; + +static struct resource datr_flash_resource __initdata = { + .start = DATR_FLASH_PHYS, + .end = DATR_FLASH_PHYS + DATR_FLASH_SIZE - 1 , + .flags = IORESOURCE_MEM, +}; + +static struct platform_device datr_flash __initdata = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &datr_flash_data, + }, + .resource = &datr_flash_resource, + .num_resources = 1, +}; + + +/* + * Input device for LEDs, reset MAINB and buttons + */ +static u16 ledr = 0xffff; +#define GPIO_RESET_VME 12 +#define GPIO_RESET_VME_MD (GPIO_RESET_VME | GPIO_OUT) + +#define GPIO_DOOR 9 +#define DOOR_FLAGS (/*IRQF_DISABLED |*/ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING) + +#define GPIO_nCS_CPLD_MD GPIO79_nCS_3_MD + +//#define GPIO_LEVEL(x) (GPLR(x) & GPIO_bit(x)) + +#define LEDR (*(volatile unsigned short *)DATR_LEDS_BASE) + +static irqreturn_t door_int(int irq, void *dev_id) { + struct input_dev *idev = dev_id; + int value = gpio_get_value(GPIO_DOOR); +#if 1 + printk("door button: %d\n", value); +#endif + input_report_key(idev, BTN_0, value); + input_sync(idev); + return IRQ_HANDLED; +} + +static int datr_event(struct input_dev *dev, unsigned int type, + unsigned int code, int value) { + if (type == EV_LED) { + if (15 == code) { + if (1 == value) { + /* force door event */ + /* Set the wrong bit value to ensure the creation of an event */ + unsigned long flags; + int val; + local_irq_save(flags); + val = gpio_get_value(GPIO_DOOR); + dev->key[BIT_MASK(BTN_0)] = !val; + input_report_key(dev, BTN_0, val); + local_irq_restore(flags); + input_sync(dev); + } + } else { + /** led status modification */ + ledr = (ledr & ~(1 << code)) | (value ? 0 : (1 << code)); + LEDR = ledr; + } + } else { + if (type == EV_FF) { + /** write a VME reset */ + if (1 == code) { + gpio_set_value(GPIO_RESET_VME, value); + } else { + /** read VME reset state */ + if (2 == code) { + input_report_key(dev, 1, gpio_get_value(GPIO_RESET_VME)); + input_sync(dev); + } + } + } else + return -1; + } + return 0; +} + +static int datr_input_init(void) { + struct input_dev *datr_input; + int err; + int irq; + + /* turn off all LEDs */ + LEDR = ledr; + datr_input = input_allocate_device(); + if (!datr_input) { + printk(KERN_ERR "failed to allocate input device\n"); + return 1; + } + datr_input->name = "datr"; + datr_input->evbit[0] = BIT_MASK(EV_KEY) | BIT(EV_LED) | BIT(EV_FF); + datr_input->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0); + datr_input->ledbit[0] = 0x8fff; + datr_input->event = datr_event; + + if((err = input_register_device(datr_input))) { + printk("failed to register input device\n"); + goto fail; + } + + if((err = gpio_request(GPIO_DOOR, "door"))) { + printk("failed to obtain door GPIO: %d\n", err); + goto fail; + } + + if((err = gpio_direction_input(GPIO_DOOR))) { + printk("failed to setup door GPIO: %d\n", err); + goto fail; + } + + gpio_request(GPIO_RESET_VME, "vacfail"); + gpio_direction_output(GPIO_RESET_VME, 0); + + /* install door interrupt handler */ + irq = gpio_to_irq(GPIO_DOOR); + + if((err = request_irq(irq, door_int, DOOR_FLAGS, "door", datr_input))) { + printk("failed to obtain door irq %d: %d\n", irq, err); + } else { + printk("datra door irq: %d\n", irq); + } +#if 1 + printk(KERN_INFO "Finished datr_input_init()\n"); +#endif + return 0; + +fail: input_free_device(datr_input); + return 1; +} + +device_initcall(datr_input_init); + +/* + * USB Device Controller + */ + +static void datr_udc_command(int cmd) +{ + switch(cmd) { + case PXA2XX_UDC_CMD_CONNECT: + printk(KERN_INFO "UDC_conn0 %#x\n", DATR_CR(0)); + DATR_CR(0) |= 1; + printk(KERN_INFO "UDC_conn1 %#x\n", DATR_CR(0)); + break; + case PXA2XX_UDC_CMD_DISCONNECT: + printk(KERN_INFO "UDC_disc0 %#x\n", DATR_CR(0)); + DATR_CR(0) &= ~1; + printk(KERN_INFO "UDC_disc1 %#x\n", DATR_CR(0)); + break; + } +} + + +static int datr_udc_is_connected(void) +{ + printk(KERN_INFO "UDC_is_conn %#x\n", DATR_CR(0)); + return (DATR_CR(0) & 2) == 0; +} + + +static struct pxa2xx_udc_mach_info udc_info __initdata = { + .udc_command = datr_udc_command, + .udc_is_connected = datr_udc_is_connected, + .gpio_pullup = -1, + .gpio_vbus = -1 +}; + +static unsigned long datr_pin_config[] __initdata = { + GPIO49_nPWE, + GPIO18_RDY, + GPIO15_nCS_1, + GPIO80_nCS_4, + GPIO91_GPIO // ISP1760 interrupt +}; + + +/* + * declare the available device resources on this board + */ +static struct platform_device *devices[] __initdata = { + &datr_flash +#ifdef CONFIG_SMC91X + ,&smc91x_device +#endif +#if defined(CONFIG_USB_ISP1760_HCD) || defined(CONFIG_USB_ISP1760_HCD_MODULE) + ,&isp1760_device +#endif +}; + +static void __init datr_init(void) +{ + /** @todo remove this temporary command which open the external bus */ + DATR_CR(0); + + /* system bus arbiter setting + * - Core_Park + * - LCD_wt:DMA_wt:CORE_Wt = 2:3:4 + */ + ARB_CNTRL = ARB_CORE_PARK | 0x234; + pxa2xx_mfp_config(ARRAY_AND_SIZE(datr_pin_config)); + +#if defined(CONFIG_USB_ISP1760_HCD) || defined(CONFIG_USB_ISP1760_HCD_MODULE) + /* Configure timing of CS4 (USB2) */ + MSC2 = (MSC2 & 0xffff0000) | 0x0234; + set_irq_type(ISP1761_IRQ, IRQ_TYPE_EDGE_FALLING); +#endif + + platform_add_devices(devices, ARRAY_SIZE(devices)); + + pxa_set_udc_info(&udc_info); + + printk("Marco %s, %x\n", __FUNCTION__, DATR_CR(0)); + DATR_CR(0) = 0xff; + printk("Marco %s, %x\n", __FUNCTION__, DATR_CR(0)); + DATR_CR(0) = 0xff; + printk("Marco %s, %x\n", __FUNCTION__, DATR_CR(0)); + DATR_CR(0) = 0; + printk("Marco %s, %x\n", __FUNCTION__, DATR_CR(0)); +} + +static struct map_desc datr_io_desc[] __initdata = { + { /* CPLD regs */ + .virtual = DATR_CTRL_BASE, + .pfn = __phys_to_pfn(DATR_CTRL_PHYS), + .length = DATR_CTRL_SIZE, + .type = MT_DEVICE + }, + { /* LEDs */ + .virtual = DATR_LEDS_BASE, + .pfn = __phys_to_pfn(DATR_LEDS_PHYS), + .length = DATR_LEDS_SIZE, + .type = MT_DEVICE + } +}; + +static void __init datr_map_io(void) +{ + pxa_map_io(); + iotable_init(datr_io_desc, ARRAY_SIZE(datr_io_desc)); + + /* initialiye sleep mode regs (wake-up sources, etc) */ + PGSR0 = 0x01308000; + PGSR1 = 0x00CF0002; + PGSR2 = 0x0E294000; + PGSR3 = 0x0000C000; + PWER = 0xC0000003; + PRER = 0x00000000; + PFER = 0x00000003; + + printk("Marco %s, testpoint\n", __FUNCTION__); + + /* configure CPLD chip select */ + MSC0 = (MSC0 & 0x0000ffff) | 0x53dc0000; +} + +MACHINE_START(DATR, "HaslerRail, Inc. DATR") + /* Maintainer: HaslerRail, Inc. */ + .phys_io = 0x40000000, + .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, + .boot_params = 0xa0000100, + .map_io = datr_map_io, + .init_irq = pxa27x_init_irq, + .init_machine = datr_init, + .timer = &pxa_timer, +MACHINE_END diff -urN linux-2.6.30.4-orig/arch/arm/mach-pxa/include/mach/datr.h linux-2.6.30.4/arch/arm/mach-pxa/include/mach/datr.h --- linux-2.6.30.4-orig/arch/arm/mach-pxa/include/mach/datr.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/arch/arm/mach-pxa/include/mach/datr.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,68 @@ +/* + * linux/include/asm-arm/arch-pxa/datr.h + * + * Copyright (C) 2007, HaslerRail, Inc. + * + * based on: + * + * linux/include/asm-arm/arch-pxa/pcm027.h + * + * (c) 2003 Phytec Messtechnik GmbH + * + * 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 + */ + +/* + * GPIOs Interrupt Source + */ +#define GPIO_DATR_ETH 52 +#define GPIO_DATR_ACFAIL + +/* + * ethernet chip (SMSC91C111) + */ +#define DATR_ETH_PHYS PXA_CS5_PHYS +#define DATR_ETH_SIZE (1*1024*1024) +#define DATR_ETH_IRQ IRQ_GPIO(GPIO_DATR_ETH) +#define DATR_ETH_IRQ_EDGE IRQ_TYPE_EDGE_RISING + +/* + * Control PLD Regs + */ +#define DATR_CTRL_PHYS (PXA_CS1_PHYS + (0 << 23)) +#define DATR_CTRL_BASE 0xea000000 +#define DATR_CTRL_SIZE (1*1024*1024) + +/* Flash memory */ +#define DATR_FLASH_PHYS 0x00000000 +#define DATR_FLASH_SIZE 0x02000000 + +/* + * LEDs + */ +#define DATR_LEDS_PHYS (PXA_CS1_PHYS + (1 << 23)) +#define DATR_LEDS_BASE 0xea100000 +#define DATR_LEDS_SIZE (1*1024*1024) + +#define DATR_CTRL_P2V(x) ((x) - DATR_CTRL_PHYS + DATR_CTRL_BASE) +#define DATR_CTRL_V2P(x) ((x) - DATR_CTRL_BASE + DATR_CTRL_PHYS) + +#ifndef __ASSEMBLY__ +# define __DATR_CTRL_REG(x) (*((volatile unsigned short *)DATR_CTRL_P2V(x))) +#else +# define __DATR_CTRL_REG(x) DATR_CTRL_P2V(x) +#endif + +#define DATR_CR(x) __DATR_CTRL_REG(DATR_CTRL_PHYS + ((x) << 1)) diff -urN linux-2.6.30.4-orig/arch/arm/mach-pxa/include/mach/debug-macro.S linux-2.6.30.4/arch/arm/mach-pxa/include/mach/debug-macro.S --- linux-2.6.30.4-orig/arch/arm/mach-pxa/include/mach/debug-macro.S 2009-07-31 00:34:47.000000000 +0200 +++ linux-2.6.30.4/arch/arm/mach-pxa/include/mach/debug-macro.S 2009-08-05 16:11:13.000000000 +0200 @@ -18,7 +18,7 @@ tst \rx, #1 @ MMU enabled? moveq \rx, #0x40000000 @ physical movne \rx, #io_p2v(0x40000000) @ virtual - orr \rx, \rx, #0x00100000 + orr \rx, \rx, #0x00700000 .endm #define UART_SHIFT 2 diff -urN linux-2.6.30.4-orig/arch/arm/mach-pxa/Kconfig linux-2.6.30.4/arch/arm/mach-pxa/Kconfig --- linux-2.6.30.4-orig/arch/arm/mach-pxa/Kconfig 2009-07-31 00:34:47.000000000 +0200 +++ linux-2.6.30.4/arch/arm/mach-pxa/Kconfig 2009-08-05 16:11:13.000000000 +0200 @@ -339,6 +339,10 @@ select PXA_SSP select PXA_HAVE_BOARD_IRQS +config MACH_DATR + bool "HaslerRail DATR" + select PXA27x + config ARCH_PXA_PALM bool "PXA based Palm PDAs" select HAVE_PWM diff -urN linux-2.6.30.4-orig/arch/arm/mach-pxa/Makefile linux-2.6.30.4/arch/arm/mach-pxa/Makefile --- linux-2.6.30.4-orig/arch/arm/mach-pxa/Makefile 2009-07-31 00:34:47.000000000 +0200 +++ linux-2.6.30.4/arch/arm/mach-pxa/Makefile 2009-08-05 16:11:13.000000000 +0200 @@ -44,6 +44,7 @@ obj-$(CONFIG_CORGI_SSP_DEPRECATED) += corgi_ssp.o corgi_lcd.o obj-$(CONFIG_MACH_POODLE) += poodle.o obj-$(CONFIG_MACH_PCM027) += pcm027.o +obj-$(CONFIG_MACH_DATR) += datr.o obj-$(CONFIG_MACH_PCM990_BASEBOARD) += pcm990-baseboard.o obj-$(CONFIG_MACH_TOSA) += tosa.o obj-$(CONFIG_MACH_EM_X270) += em-x270.o diff -urN linux-2.6.30.4-orig/drivers/block/Makefile linux-2.6.30.4/drivers/block/Makefile --- linux-2.6.30.4-orig/drivers/block/Makefile 2009-07-31 00:34:47.000000000 +0200 +++ linux-2.6.30.4/drivers/block/Makefile 2009-08-05 16:24:44.000000000 +0200 @@ -5,6 +5,7 @@ # Rewritten to use lists instead of if-statements. # +#obj-y += tffs/ obj-$(CONFIG_MAC_FLOPPY) += swim3.o obj-$(CONFIG_BLK_DEV_SWIM) += swim_mod.o obj-$(CONFIG_BLK_DEV_FD) += floppy.o diff -urN linux-2.6.30.4-orig/drivers/block/tffs/bddefs.h linux-2.6.30.4/drivers/block/tffs/bddefs.h --- linux-2.6.30.4-orig/drivers/block/tffs/bddefs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/bddefs.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,108 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/3/bddoc/src/bddefs.h-arc $ + * + * Rev 1.7 Oct 22 2007 11:34:46 einat.avidan + * update copyrights header + * + * Rev 1.6 Feb 28 2007 09:58:42 einat.avidan + * No change + * + * Rev 1.5.1.2 Sep 11 2006 13:45:10 yaniv.iarovici + * Legal header added + * + * Rev 1.5.1.1 Aug 22 2006 13:22:06 Yaniv.Iarovici + * Add 'extern "c"' on vols[] external definition + * + * Rev 1.5.1.0 Aug 08 2006 15:55:34 Polina.Marimont + * DOC Driver 1.0 initial + */ + +#ifndef BDDEFS_H +#define BDDEFS_H + +#include "defs.h" +#include "fltl.h" +#include "flbuffer.h" +#include "docsys.h" + + +typedef struct { + FLSByte flags; /* See description in flreq.h */ + + FLDword sectorsInVolume; + unsigned mountCount; /* can be opened/closed several times */ + + FLMutex* volExecInProgress; + FLFlash FAR2* flash; /* flash structure for low level operations */ + TL tl; /* Translation layer methods */ + FLSocket *socket; /* Pointer to socket */ + + FLBoolean globalAttFlag; /* indication of global attention flag */ +} Volume; + +#define VOLUME_NOT_OCCUPIED 0 +#define VOLUME_LOW_LVL_MOUNTED 1 /* Volume is mounted for low level operations */ +#define VOLUME_MOUNTED 2 /* Volume is mounted */ +#define VOLUME_12BIT_FAT 4 /* Volume uses 12-bit FAT */ +#define VOLUME_ABS_MOUNTED 8 /* Volume is mounted for abs calls */ +#define VOLUME_OCCUPIED 32 /* Volume record in use */ +#define VOLUME_MOUNTED_NO_MBR 64 +#define VOLUME_MOUNTED_ON_RANGE 128 + + +#define execInProgress (pVol->volExecInProgress) + +#ifdef __cplusplus +extern "C" { +#endif +extern Volume vols[FL_VOLUMES]; +#ifdef __cplusplus +} +#endif + +FLStatus lockForIO(FLByte socket, FLByte partition, FLBoolean onOff); +void setTL(FLByte socket, FLByte partition, TL * fsVol); + +#endif diff -urN linux-2.6.30.4-orig/drivers/block/tffs/bdkemul.h linux-2.6.30.4/drivers/block/tffs/bdkemul.h --- linux-2.6.30.4-orig/drivers/block/tffs/bdkemul.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/bdkemul.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,135 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Test for 7.x/src/H3/bdkemul.h-arc $ + * + * Rev 1.15 Dec 11 2007 12:25:10 einat.avidan + * Add format start and format complete signatures in disk user attributes + * + * Rev 1.14 Oct 22 2007 11:34:48 einat.avidan + * update copyrights header + * + * Rev 1.13 Sep 11 2006 13:45:10 yaniv.iarovici + * Legal header added + * + * Rev 1.12 Aug 09 2006 17:34:14 Polina.Marimont + * initial for DOC Driver 1.0 + * + * Rev 1.11 May 28 2006 12:48:42 polina.marimont + * comments + * + * Rev 1.10 May 17 2006 12:51:04 polina.marimont + * 1. DOCH_DiskUserAttrWithBinary - changed to support floors + * 2. DOCH macros use instead of numerical constants + * + * Rev 1.9 Mar 22 2006 17:35:46 DoronC + * Bug fix - add signature to disk attributes in order to use only + * format made by TrueFFS 7.1 and not by host SDK. + * Other format will force reformating of the media. + * + * Rev 1.8 Feb 16 2006 11:32:36 DoronC + * Store binary partition flags in the attributes and return then + * when requested by extendedInfo for compatability with legacy + * devices. + * + * Rev 1.7 Feb 14 2006 10:50:04 DoronC + * Remove large variables from stack. use one global buffer for + * all large buffers needs. + */ +#ifndef BDKEMUL_H +#define BDKEMUL_H + +#include "part_inf.h" + +/*Unit size*/ +#define BDK_SECTORS_IN_UNIT 0x200 +#define BDK_UNIT_SIZE (BDK_SECTORS_IN_UNIT< Erasable Block Size + * flWriteFault - fail in buffer writing + * flNoSpaceInVolume - end of media was prematurely reached + *-------------------------------------------------------------------*/ +#define bdkWriteBlock(ioreq) bdCall(FL_BINARY_WRITE_BLOCK,ioreq) + + +/*------------------------------------------------------------------- + * bdkErase - erase given number of blockdsin the BDK area. + * + * Erase given number of blockds in the binary sub partition. + * + * Parameters: ioreq + * 'irHandle' - Drive number (0, 1, ...) + * bits 7-4 - Partition # (zero based) + * bits 3-0 - Socket # (zero based) + * 'irData' - bdkParams record + * startingBlock - unit number of the sub-partition to start erasing from + * length - number of blocks to erase + * oldSign - signature of the sub-partition + * + * Return: flOK - success + * flBadLength - buffer length > Erasable Block Size + * flWriteFault - fail in buffer writing + * flNoSpaceInVolume - end of media was prematurely reached + *-------------------------------------------------------------------*/ +#define bdkErase(ioreq) bdCall(FL_BINARY_ERASE,ioreq) + + + +/*------------------------------------------------------------------- + * bdkCreate - create new BDK partition . + * + * Init create operations on the DiskOnChip starting at 'startUnit', with + * a # of 'units' and 'signature'. + * + * Note : Blocks in the DiskOnChip are marked with a 4-character signature + * followed by a 4-digit hexadecimal number. + * + * Parameters: ioreq + * 'irHandle' - Drive number (0, 1, ...) + * bits 7-4 - Partition # (zero based) + * bits 3-0 - Socket # (zero based) + * 'irData' - bdkParams record + * length - number of blocks to create + * oldSign - signature of the sub-partition + * newSign - the replacing signature + * + * Return: flOK - success + * flBadLength - buffer length > Erasable Block Size + * flWriteFault - fail in buffer writing + * flNoSpaceInVolume - end of media was prematurely reached + *-------------------------------------------------------------------*/ +#define bdkCreate(ioreq) bdCall(FL_BINARY_CREATE,ioreq) + +/*----------------------------------------------------------------------*/ +/* b d k P a r t i t i o n I n f o */ +/* */ +/* Parameters: */ +/* irHandle : volume number */ +/* irData : pointer to structure that hold socket */ +/* parameters */ +/* irLength : Physical size of the binary volume */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed. */ +/*----------------------------------------------------------------------*/ +#define bdkPartitionInfo(ioreq) bdCall(FL_BINARY_PARTITION_INFO,ioreq) + + +/* DEEP_POWER_DOWN 1 defined in flflash.h */ + + +/*----------------------------------------------------------------------*/ +/* f l W r i t e I P L */ +/* */ +/* Place a user buffer to both copies of the IPL area */ +/* */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (0,1,..) */ +/* 4 LSB - Socket number */ +/* irData : Pointer to user buffer */ +/* irLength : Size of the buffer */ +/* irFlags : See flags bellow */ +/* FL_IPL_MODE_NORMAL */ +/* FL_IPL_VIRTUAL_RAM_MODE */ +/* FL_DOC_IPL_PAGED_RAM_MODE */ +/* FL_IPL_128K_WINDOW_MODE */ +/* FL_IPL_SWAP_BYTES_MODE */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flWriteIPL(ioreq) bdCall(FL_WRITE_IPL,ioreq) + +/*----------------------------------------------------------------------*/ +/* r e a d I P L */ +/* */ +/* Read IPL to user buffer. */ +/* */ +/* Note : Read length must be a multiplication of 512 bytes */ +/* Note : Causes DiskOnChip Millennium Plus to download (i,e protection */ +/* key will be removed from all partitions. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (0,1,..) */ +/* 4 LSB - Socket number */ +/* irData : Pointer to user buffer */ +/* irLength : Size of the buffer */ +/* irCount : Used IPL size on the media */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flReadIPL(ioreq) bdCall(FL_READ_IPL,ioreq) + + + + +/*----------------------------------------------------------------------*/ +/* f l I n i t */ +/* */ +/* Initializes the FLite system. */ +/* */ +/* Calling this function is optional. If it is not called, */ +/* initialization will be done automatically on the first FLite call. */ +/* This function is provided for those applications who want to */ +/* explicitly initialize the system and get an initialization status. */ +/* */ +/* Calling flInit after initialization was done has no effect. */ +/* */ +/* Parameters: */ +/* None */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ +TFFS_DLL_API FLStatus NAMING_CONVENTION flInit(void); +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +/*----------------------------------------------------------------------*/ +/* f l E x i t */ +/* */ +/* If the application ever exits, flExit should be called before exit. */ +/* flExit flushes all buffers, closes all open files, powers down the */ +/* sockets and removes the interval timer. */ +/* */ +/* Parameters: */ +/* None */ +/* */ +/* Returns: */ +/* Nothing */ +/*----------------------------------------------------------------------*/ +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ +TFFS_DLL_API void NAMING_CONVENTION flExit(void); +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +/*----------------------------------------------------------------------*/ +/* f l G e t P h y s i c a l I n f o */ +/* */ +/* Get physical information of the media. The information includes */ +/* JEDEC ID, unit size and media size. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (0,1,..) */ +/* irData : Address of user buffer to read physical */ +/* information into. */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/* irLength : Window base address. note mast be cast to */ +/* unsigned. */ +/*----------------------------------------------------------------------*/ +#define flGetPhysicalInfo(ioreq) bdCall(FL_GET_PHYSICAL_INFO, ioreq) + + +/*----------------------------------------------------------------------*/ +/* f l E x t e n d e d G e t D i s k I n f o */ +/* */ +/* Returns general information about the Device and a specific partition */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Must be set to 0 */ +/* bits 3-0 - Socket # (zero based) */ +/* irCount : Partition number */ +/* irFlags : Either FL_BDK_PARTITION or FL_DISK_PARTITION */ +/* irData : Address of FLExtendedDiskInfo structure */ +/* irLength : Floor number to access - FL_ALL_FLOORS */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flGetExtendedDiskInfo(ioreq) bdCall(FL_GET_EXTENDED_DISK_INFO,ioreq) + + + + + +/*----------------------------------------------------------------------*/ +/* f l I d e n t i f y P r o t e c t i o n */ +/* b d k I d e n t i f y P r o t e c t i o n */ +/* f l I p l I d e n t i f y P r o t e c t i o n */ +/* */ +/* Returns the specified partitions protection attributes */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/* irFlags CHANGEABLE_PROTECTION - changeable protection type */ +/* PROTECTABLE - partition can recieve protection */ +/* READ_PROTECTED - partition is read protected */ +/* WRITE_PROTECTED - partition is write protected */ +/* LOCK_ENABLED - HW lock signal is enabled */ +/* LOCK_ASSERTED - HW lock signal is asserted */ +/* KEY_INSERTED - key is inserted (not currently */ +/* protected. */ +/*----------------------------------------------------------------------*/ +#define flIdentifyProtection(ioreq) bdCall(FL_PROTECTION_GET_TYPE,ioreq) +#define bdkIdentifyProtection(ioreq) bdCall(FL_BINARY_PROTECTION_GET_TYPE,ioreq) +#define flIplIdentifyProtection(ioreq) bdCall(FL_IPL_PROTECTION_GET_TYPE,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l I n s e r t P r o t e c t i o n K e y */ +/* b d k I n s e r t P r o t e c t i o n K e y */ +/* f l I p l I n s e r t P r o t e c t i o n K e y */ +/* */ +/* Insert the protection key in order to remove the protection of the */ +/* partititon specified by the drive handle */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irData : pointer to an 8 bytes key array */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flInsertProtectionKey(ioreq) bdCall(FL_PROTECTION_INSERT_KEY,ioreq) +#define bdkInsertProtectionKey(ioreq) bdCall(FL_BINARY_PROTECTION_INSERT_KEY,ioreq) +#define flIplInsertProtectionKey(ioreq) bdCall(FL_IPL_PROTECTION_INSERT_KEY,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l R e m o v e P r o t e c t i o n K e y */ +/* b d k R e m o v e P r o t e c t i o n K e y */ +/* f l I p l R e m o v e P r o t e c t i o n K e y */ +/* */ +/* Remove the protection key making the partition protected again */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flRemoveProtectionKey(ioreq) bdCall(FL_PROTECTION_REMOVE_KEY,ioreq) +#define bdkRemoveProtectionKey(ioreq) bdCall(FL_BINARY_PROTECTION_REMOVE_KEY,ioreq) +#define flIplRemoveProtectionKey(ioreq) bdCall(FL_IPL_PROTECTION_REMOVE_KEY,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l H a r d w a r e P r o t e c t i o n L o c k */ +/* b d k H a r d w a r e P r o t e c t i o n L o c k */ +/* */ +/* Enabled or disabled the affect of the hardware LOCK signal */ +/* The hardware lock signal disables the removal of protection through */ +/* the key therefore the partition will remain protected until the */ +/* hardware LOCK signal will be removed */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irFlags : LOCK_ENABLED locks the partition otherwise */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flHardwareProtectionLock(ioreq) bdCall(FL_PROTECTION_SET_LOCK,ioreq) +#define bdkHardwareProtectionLock(ioreq) bdCall(FL_BINARY_PROTECTION_CHANGE_LOCK,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l C h a n g e P r o t e c t i o n K e y */ +/* b d k C h a n g e P r o t e c t i o n K e y */ +/* f l I p l C h a n g e P r o t e c t i o n K e y */ +/* */ +/* Changes the current protection key with a new one. */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irData : Pointer to the new 8 bytes key array */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flChangeProtectionKey(ioreq) bdCall(FL_PROTECTION_CHANGE_KEY,ioreq) +#define bdkChangeProtectionKey(ioreq) bdCall(FL_BINARY_PROTECTION_CHANGE_KEY,ioreq) +#define flIplChangeProtectionKey(ioreq) bdCall(FL_IPL_PROTECTION_CHANGE_KEY,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l C h a n g e P r o t e c t i o n T y p e */ +/* b d k C h a n g e P r o t e c t i o n T y p e */ +/* f l I p l C h a n g e P r o t e c t i o n T y p e */ +/* */ +/* Changes the protection attributes of the partitions. */ +/* In order for a partition to change its protection type (without */ +/* reformating the media) it must have the CHANGEABLE_PRTOECTION */ +/* attribute. */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flChangeProtectionType(ioreq) bdCall(FL_PROTECTION_CHANGE_TYPE,ioreq) +#define bdkChangeProtectionType(ioreq) bdCall(FL_BINARY_PROTECTION_SET_TYPE,ioreq) +#define flIplChangeProtectionType(ioreq) bdCall(FL_IPL_PROTECTION_CHANGE_TYPE,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l A p p l y S t i c k y L o c k */ +/* */ +/* Enable the sticky lock mode to all relevant partitions */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Must be set to 0 */ +/* bits 3-0 - Socket # (zero based) */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flApplyStickyLock(ioreq) bdCall(FL_PROTECTION_STICKY_LOCK,ioreq) + +#ifdef FL_SLPP +/*SLPP Specific*/ +/*----------------------------------------------------------------------*/ +/* f l S L P P U n l o c k R a n g e */ +/* */ +/* Unlock a range of sectors on a sector protected partition. */ +/* */ +/* Parameters: */ +/* irHandle : Bits 3-0 - Socket # (zero based) */ +/* irCount : First sector to unlock */ +/* irLength : Number of sectors to unlock */ +/* irData : Pointer to an 8 bytes passkey array */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flSLPPUnlockRange(ioreq) bdCall(FL_SLPP_UNLOCK_RANGE,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l S L P P U n l o c k E n t i r e P a r t i t i o n */ +/* */ +/* Unlock all sectors on a sector protected partition. */ +/* */ +/* Parameters: */ +/* irHandle : Bits 3-0 - Socket # (zero based) */ +/* irData : Pointer to an 8 bytes passkey array */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flSLPPUnlockEntirePartition(ioreq) bdCall(FL_SLPP_UNLOCK_ENTIRE_PARTITION,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l S L P P L o c k R a n g e */ +/* */ +/* Lock a range of sectors on a sector protected partition. */ +/* */ +/* Parameters: */ +/* irHandle : Bits 3-0 - Socket # (zero based) */ +/* irCount : First sector to lock */ +/* irLength : Number of sectors to lock */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flSLPPLockRange(ioreq) bdCall(FL_SLPP_LOCK_RANGE,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l S L P P S t i c k y L o c k R a n g e */ +/* */ +/* Sticky lock a range of sectors on a sector protected partition. */ +/* */ +/* Parameters: */ +/* irHandle : Bits 3-0 - Socket # (zero based) */ +/* irCount : First sector to sticky lock */ +/* irLength : Number of sectors to sticky lock */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flSLPPStickyLockRange(ioreq) bdCall(FL_SLPP_STICKY_LOCK_RANGE,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l S L P P R e p o r t L o c k e d R a n g e s */ +/* */ +/* Report currently defined unlocked/stick locked ranges on a sector */ +/* protected partition. */ +/* */ +/* Parameters: */ +/* irHandle : Bits 3-0 - Socket # (zero based) */ +/* irData : Pointer to DOCH_SLPPReport structure */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/* irCount : Number of currently defined ranges */ +/*----------------------------------------------------------------------*/ +#define flSLPPReportLockedRanges(ioreq) bdCall(FL_SLPP_REPORT_LOCKED_RANGES,ioreq) + +#endif /*FL_SLPP*/ + +/*----------------------------------------------------------------------*/ +/* f l O T P S i z e */ +/* */ +/* Get the OTP size and stated */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* irLength : The size of the used OTP area in bytes */ +/* irCount : The size of the OTP ara in bytes */ +/* irFlags : LOCKED_OTP for a locked area otherwise unlocked */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flOTPSize(ioreq) bdCall(FL_OTP_SIZE,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l O T P W r i t e A n d L o c k */ +/* */ +/* Write to the OTP area while locking it at the end. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* irData : pointer to user buffer to write from */ +/* irLength : number of bytes to write */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flOTPWriteAndLock(ioreq) bdCall(FL_OTP_WRITE,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l O T P R e a d */ +/* */ +/* Read from the OTP area */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* irData : pointer to user buffer to read into */ +/* irLength : number of bytes to read */ +/* irCount : offset to read from (starting at the begining of */ +/* the OTP area */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flOTPRead(ioreq) bdCall(FL_OTP_READ,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l G e t U n i q u e I D */ +/* */ +/* Returns the 16 bytes device unique ID */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* irData : pointer to a 16 bytes buffer to read into the */ +/* unique ID data */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/* irData : 16 bytes unique ID buffer */ +/*----------------------------------------------------------------------*/ +#define flGetUniqueID(ioreq) bdCall(FL_UNIQUE_ID,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l G e t C u s t o m e r I D */ +/* */ +/* Returns the 4 bytes customer ID */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* irData : pointer to a 4 bytes buffer to read into the */ +/* customer ID */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/* irData : 4 bytes unique ID buffer */ +/*----------------------------------------------------------------------*/ +#define flGetCustomerID(ioreq) bdCall(FL_CUSTOMER_ID,ioreq) + + +/*----------------------------------------------------------------------*/ +/* f l D e e p P o w e r D o w n M o d e */ +/* */ +/* Forces the device into and out of the deep power down mode */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* irFlags : DEEP_POWER_DOWN forces the low power consumption */ +/* mode. otherwise turning to the regular mode */ +/* */ +/* Returns: None */ +/*----------------------------------------------------------------------*/ +#define flDeepPowerDownMode(ioreq) bdCall(FL_DEEP_POWER_DOWN_MODE,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l R e c o v e r F r o m P o w e r L o s s */ +/* */ +/* Recover from a power OFF without full TrueFFS initialization. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* */ +/* Returns: None */ +/*----------------------------------------------------------------------*/ +#define flRecoverFromPowerLoss(ioreq) bdCall(FL_RECOVER_FROM_POWER_LOSS,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l C l e a r Q u i c k M o u n t I n f o */ +/* */ +/* Clear all quick mount informtion. */ +/* */ +/* Must be called before calling mount volume routines. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* : Partition number ( 0,1,2... ) */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flClearQuickMountInfo(ioreq) bdCall(FL_CLEAR_QUICK_MOUNT_INFO,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l W r i t e Q u i c k M o u n t S t a t u s */ +/* */ +/* Get the status of the quick mount information. */ +/* */ +/* Can NOT be called before calling mount volume routines. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* : Partition number ( 0,1,2... ) */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flWriteQuickMountInfo(ioreq) bdCall(FL_WRITE_QUICK_MOUNT_INFO,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l G e t Q u i c k M o u n t S t a t u s */ +/* */ +/* Get the status of the quick mount information. */ +/* */ +/* Can be called before calling mount volume routines. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* : Partition number ( 0,1,2... ) */ +/* irFlags : return the quick mount info: */ +/* FL_ON if valid FL_OFF if not */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flGetQuickMountStatus(ioreq) bdCall(FL_GET_QUICK_MOUNT_STATUS,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l H w C o n f i g */ +/* */ +/* his routine enables to control DiskOnChip H/W features. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* irFlags : Descrbing H/W configuration Type */ +/* irLength : New value to use - Different for each H/W */ +/* configuration type chosen. */ +/* */ +/* Returns: None */ +/*----------------------------------------------------------------------*/ +#define flHwConfig(ioreq) bdCall(FL_HW_CONFIG,ioreq) + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ +/*----------------------------------------------------------------------*/ +/* f l B u i l d G e o m e t r y */ +/* */ +/* Get C/H/S information of the disk according to number of sectors. */ +/* */ +/* Parameters: */ +/* capacity : Number of Sectors in Volume */ +/* cylinders : Pointer to Number of Cylinders */ +/* heads : Pointer to Number of Heads */ +/* sectors : Pointer to Number of Sectors per Track */ +/* oldFormat : True for one sector per culoster */ +/* wIrHandle : Disk partition handle to proccess */ +/* */ +/*----------------------------------------------------------------------*/ +TFFS_DLL_API void NAMING_CONVENTION flBuildGeometry(FLDword capacity, FLDword FAR2 *cylinders, + FLDword FAR2 *heads,FLDword FAR2 *sectors, FLBoolean oldFormat, FLWord wIrHandle); +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +/*----------------------------------------------------------------------*/ +/* r e a d B B T */ +/* */ +/* Read Bad Blocks Table of device to user buffer */ +/* */ +/* Note: the buffer is not initialized by the function */ +/* */ +/* Parameters: */ +/* irData : User buffer. */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/* irLength : returns the media size */ +/* irFlags : returns the actual number of badBlocks */ +/*----------------------------------------------------------------------*/ +#define flReadBBT(ioreq) bdCall(FL_READ_BBT,ioreq) + + + + +/*----------------------------------------------------------------------*/ +/* f l O T P S i z e */ +/* */ +/* Get the OTP size and stated */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* irLength : The size of the used OTP area in bytes */ +/* irCount : The size of the OTP ara in bytes */ +/* irFlags : LOCKED_OTP for a locked area otherwise unlocked */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ + +#define flMCOTPSize(ioreq) bdCall(FL_MCOTP_SIZE,ioreq) +/* LOCKED_OTP 1 defined in flflash.h */ + +/*----------------------------------------------------------------------*/ +/* f l O T P R e a d */ +/* */ +/* Read from the OTP area */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* irData : pointer to user buffer to read into */ +/* irLength : number of bytes to read */ +/* irCount : offset to read from (starting at the begining of */ +/* the OTP area */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ + +#define flMCOTPRead(ioreq) bdCall(FL_MCOTP_READ,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l O T P W r i t e A n d L o c k */ +/* */ +/* Write to the OTP area while locking it at the end. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* irData : pointer to user buffer to write from */ +/* irLength : number of bytes to write */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ + +#define flMCOTPWriteAndLock(ioreq) bdCall(FL_MCOTP_WRITE,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l F o r m a t F S */ +/* */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (0, 1, ...) */ +/* bits 11-8 - Logical partition in Flash partition (zero based)*/ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irSectorNo : First absolute sector of logical partition */ +/* (if bit 13 is set) */ +/* irSectorCount : Number of sectors in logical partition */ +/* (if bit 13 is set) */ +/* irData : Address of the FATFormatParams structure */ +/* irFlags : */ +/* bit 14 - FL_DO_NOT_UPDATE_MBR */ +/* bit 13 - FL_MEDIA_WITHOUT_MBR */ +/* bit 12 - FL_MOUNT_ON_GIVEN_RANGE */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flFormatFS(ioreq) formatCall(FL_FORMAT_FS,ioreq) + + +/*----------------------------------------------------------------------*/ +/* f o r m a t C a l l */ +/* */ +/* Common entry-point to all file-system format functions. Macros are */ +/* to call individual function, which are separately described below. */ +/* */ +/* Parameters: */ +/* function : file-system function code (listed below) */ +/* ioreq : IOreq structure */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ +TFFS_DLL_API FLStatus NAMING_CONVENTION formatCall(FLFunctionNo functionNo, IOreq FAR2 *ioreq); +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +/*----------------------------------------------------------------------*/ +/* */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irCount : Number of LogicalPartitionParams structures */ +/* irData : Address of array of LogicalPartitionParams structures */ +/* irFlags : 0 - reserved */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flCreateLogicalPartitions(ioreq) formatCall(FL_CREATE_LOGICAL_PARTITIONS,ioreq) + +/*----------------------------------------------------------------------*/ +/* */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (0, 1, ...) */ +/* bits 11-8 - Logical partition in Flash partition (zero based)*/ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irFlags : 0 - reserved */ +/* irData : Address of the LogPartitionInfo structure */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flFindLogicalPartition(ioreq) formatCall(FL_FIND_LOGICAL_PARTITION,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D o c h P a s s T h r o u g h */ +/* */ +/* Passes ATA command directly to the DOCH device. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* irData : pointer to user buffer (for DATA IN and DATA out */ +/* commands) */ +/* irLength : number of sectors in buffer, pointed to by irData*/ +/* irCount : bits 0..1 - pass through operation flow, where */ +/* 0 - No Data(CTRL), 1 - Data IN, 2 - Data OUT */ +/* bit 2 - 1, when interrupt should be used, */ +/* 0 - otherwise */ +/* bits 4..7 - frame size exponent, should be set */ +/* to 0 for now - 1 sector */ +/* irPath : pointer to buffer from type DOCH_Registers* */ +/* IN - input registers, OUT - out registers */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDochPassThrough(ioreq) bdCall(FL_DOCH_PASS_THROUGH,ioreq) + +#endif /* BLOCKDEV_H */ diff -urN linux-2.6.30.4-orig/drivers/block/tffs/_common.h linux-2.6.30.4/drivers/block/tffs/_common.h --- linux-2.6.30.4-orig/drivers/block/tffs/_common.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/_common.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,124 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ + +/***********************************************************************************/ +/* */ +/* Header file containing definitions used by external API */ +/* */ +/***********************************************************************************/ + +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/version 7.0/TrueFFS FS/src/mdoc/_common.h-arc $ + * + * Rev 1.3 Oct 22 2007 11:34:46 einat.avidan + * update copyrights header + * + * Rev 1.2 Sep 11 2006 13:45:10 yaniv.iarovici + * Legal header added + * + * Rev 1.1 Aug 09 2006 16:52:44 Polina.Marimont + * initial for DOC Driver 1.0 + */ + +#ifndef _COMMON_H +#define _COMMON_H + +/**************************************************************************/ +/* General types definitions */ +/* TrueFFS interface of all packages uses the following types as the */ +/* variable definision. */ +/**************************************************************************/ + +typedef int FLBoolean; +typedef unsigned char FLByte; /* 8 bit unsigned variable */ +typedef unsigned short FLWord; /* 16 bit unsigned variable */ +typedef unsigned long FLDword; /* 32 bit unsigned variable */ +typedef unsigned int FLNative; /* Native variable at least 16 bits */ +typedef signed char FLSByte; /* 8 bit signed variable */ +typedef signed short FLSWord; /* 16 bit signed variable */ +typedef signed long FLSDword; /* 32 bit signed variable */ +typedef int FLSNative; /* Signed native variable at least 16 bits */ +typedef FLSWord FLWchar; /* Unicode type variable */ +typedef FLDword CardAddress ; /* Physical offset on card */ + +/**************************************************************************/ +/* I O r e q */ +/* */ +/* IOreq is a common structure passed to all TrueFFS functions. */ +/* Refer to the description of individual functions for specific usage */ +/* of fields. Some fields have different names when used by different */ +/* functions, hence the use of unions. */ +/* */ +/**************************************************************************/ + +typedef unsigned FLHandle; /* Handle of an open file or drive. */ + /* Actually an index to file table or */ + /* drive table. */ + + +typedef struct { + FLHandle irHandle; /* Handle of file or drive for operation*/ + FLDword irFlags; /* function-specific flags */ + void * irPath; /* path of file for operation */ + void * irData; /* Pointer to user-buffer for operation */ + FLSDword irLength; /* No. of bytes, size or position for */ + /* operation */ + FLSDword irCount; /* Count or offset for operaion */ +} IOreq; + +/**************************************************************************/ +/* Special ioreq field names: */ +/* IOReq structure is the basic IO type used for all TrueFFS calls. */ +/* Some of the fields has additional name for more trivial use of the */ +/* function. The duplicate names are defined below. */ +/**************************************************************************/ +#define irSectorCount irCount +#define irSectorNo irLength +#define irByteCount irCount +#define irAddress irLength + +#define FL_GET_SOCKET_FROM_HANDLE(ioreq) (FLByte)((ioreq)->irHandle & 0x0f) +#define FL_GET_FLASH_PARTITION_FROM_HANDLE(ioreq) (FLByte)(((ioreq)->irHandle & 0xf0) >> 4) + +#endif /*_COMMON_H*/ + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/defs.c linux-2.6.30.4/drivers/block/tffs/defs.c --- linux-2.6.30.4-orig/drivers/block/tffs/defs.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/defs.c 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,341 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/DocDriver/TrueFFS BD/src/defs.c-arc $ + * + * Rev 1.8 Oct 22 2007 11:34:48 einat.avidan + * update copyrights header + * + * Rev 1.7 Oct 29 2006 11:27:26 Yaniv.Iarovici + * Removed unusable variable - 'readBackBuffer'. + * + * Rev 1.6 Oct 29 2006 10:59:40 Yaniv.Iarovici + * Removed unused variable - 'volBuffers'. + * + * Rev 1.5 Oct 09 2006 14:05:12 yaniv.iarovici + * Removed legacy devices related code and definitions + * + * Rev 1.4 Oct 05 2006 11:00:18 yaniv.iarovici + * Fixed compilation warnings. + * + * Rev 1.3 Sep 13 2006 10:43:00 yaniv.iarovici + * Fix compilation warnings + * + * Rev 1.2 Sep 11 2006 13:45:12 yaniv.iarovici + * Legal header added + * + * Rev 1.1 Aug 22 2006 13:22:20 Yaniv.Iarovici + * Remove decleration fo 'void flInitGlobalVars(void)' + * + * Rev 1.0 Aug 08 2006 15:47:24 Polina.Marimont + * Initial revision. + */ + + +#include "flcustom.h" +#include "flchkdef.h" +#include "flsystyp.h" +#include "blockdev.h" +#include "bddefs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*============================================================================*/ +/*==== from blockdev.c */ +/********************* Global variables Start **************************/ + +Volume vols[FL_VOLUMES]; +static FLBoolean initDone = FALSE; /* Initialization not done yet */ +static FLBoolean initGlobalVarsDone = FALSE; /* Initialization of environment */ + /* and access type variables not */ + /* done yet. */ +unsigned noOfDrives; +/* + * bus configuration + * DiskOnChip minimal bus width + */ +#ifndef FL_NO_USE_FUNC +FLDword flBusConfig[FL_SOCKETS]; +#endif /* FL_NO_USE_FUNC */ +/*----------------------------------------------------------------------*/ +/* f l I n i t */ +/* */ +/* Initializes the FLite system, sockets and timers. */ +/* */ +/* Calling this function is optional. If it is not called, */ +/* initialization will be done automatically . */ +/* This function is provided for those applications who want to */ +/* explicitly initialize the system and get an initialization status. */ +/* */ +/* Calling flInit after initialization was done has no effect. */ +/* */ +/* Parameters: */ +/* None */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ + +FLStatus _flInit(void) +{ + unsigned volNo; + Volume * pVol = vols; + + if (initDone) + return flOK; + + + flInitGlobalVars(); + +#ifdef FL_ENVIRONMENT_VARS + + /* Call users initialization routine + */ + flSetEnvVar(); + +#endif /* FL_ENVIRONMENT_VARS */ + + /* + * 1) Mark all the volumes as not used and free to be allocated. + * 2) Clear password in order to make it invalid. + */ + + tffsset(vols,0,sizeof(vols)); + + for (volNo = 0,pVol = vols; volNo < FL_VOLUMES; volNo++,pVol++) + { + /* The actual number of sockets is not yet known and will be retrieved by + * flRegisterComponents routine by the socket components. For now supply + * each of the possible sockets with its buffer and socket number. + */ + if ( volNo < FL_SOCKETS) + { + pVol->socket = flSocketOf(volNo); + pVol->flash = flFlashOf((FLByte)volNo); + tffsset(pVol->socket,0,sizeof(FLSocket)); + pVol->socket->volNo = volNo; + } + else + { + pVol->flash = NULL; + } + pVol->volExecInProgress = NULL; + } + + +#ifdef FL_BACKGROUND + flCreateBackground(); +#endif + noOfDrives = 0; + noOfSockets = 0; + return flOK; +}/*_flInit*/ + + +/*----------------------------------------------------------------------*/ +/* f l I n i t G l o b a l V a r s */ +/* */ +/* Initializes the FLite system, environment and access type variables. */ +/* */ +/* Parameters: */ +/* None */ +/* */ +/* Returns: */ +/* None */ +/*----------------------------------------------------------------------*/ + +void flInitGlobalVars(void) +{ + FLFlash * flash; + int i,j; + + if(initGlobalVarsDone == TRUE) + return; + + /* Do not initialize variables on next call */ + initGlobalVarsDone = TRUE; + initDone = FALSE; + + /* + * Set default values to per socket/volume variables + */ + + for(i=0; i< FL_SOCKETS; i++) + { + flash = flFlashOf((FLByte)i); + /* tffsset is not yet initialized */ + for(j=0;j<(int)sizeof(FLFlash);j++) + { + ((FLByte *)flash)[j] = 0; + } +#ifndef FL_NO_USE_FUNC + flBusConfig[i] = FL_DEFAULT_BUS_MODE(i); +#endif /* FL_NO_USE_FUNC */ + + } +}/*flInitGlobalVars*/ + +/*============================================================================*/ + +/*============================================================================*/ +/*==== from flflash.c */ +static FLFlash flashes[FL_SOCKETS]; + + +/************************************************************************/ +/************************************************************************/ +/*** ***/ +/*** E X P O R T E D R O U T I N E S ***/ +/*** ***/ +/************************************************************************/ +/************************************************************************/ + +/*----------------------------------------------------------------------*/ +/* f l F l a s h O f */ +/* */ +/* Gets the flash connected to a volume no. */ +/* */ +/* Parameters: */ +/* volNo : Volume no. for which to get flash */ +/* */ +/* Returns: */ +/* flash of volume no. */ +/*----------------------------------------------------------------------*/ +TFFS_DLL_API FLFlash * NAMING_CONVENTION flFlashOf(FLByte volNo) +{ + return &flashes[volNo]; +} + +/*============================================================================*/ +#ifdef __cplusplus +} +#endif + + + +/*============================================================================*/ +/*=== from bdstub.c */ +#include "dochstub.h" +/*----------------------------------------------------------------------*/ +/* Function name : lockForIO*/ +/* Description : */ +/* Return type : FLStatus */ +/* Argument : FLByte socket*/ +/* Argument : FLByte partition*/ +/* Argument : FLBoolean onOff*/ +/*----------------------------------------------------------------------*/ +FLStatus lockForIO(FLByte socket, FLByte partition, FLBoolean onOff) +{ + +#if (FS_SOCKETS < FL_SOCKETS) || (FS_MAX_TL_PARTITIONS < FL_MAX_TL_PARTITIONS) + /* then caller's check is not good enough */ + if ((socket >= FL_SOCKETS) || (partition >= FL_MAX_TL_PARTITIONS)) + return flBadDriveHandle; +#endif + + checkStatus(dochSetBusy(socket, onOff, partition)); /* take DOCH mutex */ + return flOK; +}/*lockForIO()*/ +/*============================================================================*/ + + +/*============================================================================*/ +/*=== from flsocket.c */ +FLByte noOfSockets; /* No. of drives actually registered */ + +static FLSocket sockets[FL_SOCKETS]; + + +/*----------------------------------------------------------------------*/ +/* f l S o c k e t O f */ +/* */ +/* Gets the socket connected to a volume no. */ +/* */ +/* Parameters: */ +/* volNo : Volume no. for which to get socket */ +/* */ +/* Returns: */ +/* socket of volume no. */ +/*----------------------------------------------------------------------*/ + +FLSocket *flSocketOf(unsigned volNo) +{ + return &sockets[volNo]; +} + +/*----------------------------------------------------------------------*/ +/* u d a t e S o c k e t P a r a m e t e r s */ +/* */ +/* Pass socket parameters to the socket interface layer. */ +/* This function should be called after the socket parameters (like */ +/* size and base) are known. If these parameters are known at */ +/* registration time then there is no need to use this function, and */ +/* the parameters can be passed to the registration routine. */ +/* The structure passed in irData is specific for each socket interface.*/ +/* */ +/* Note : When using DiskOnChip this routine returns the socekt */ +/* parameters instead of initializing them. */ +/* */ +/* Parameters: */ +/* vol : Pointer identifying drive */ +/* params : Record returning (or sending) the flsocket record */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success */ +/*----------------------------------------------------------------------*/ +FLStatus updateSocketParameters(FLSocket * pVol, void FAR1 *params) +{ + if (pVol->updateSocketParams) + pVol->updateSocketParams(pVol, params); + + return flOK; +} + +/*============================================================================*/ + +/*end of file*/ + + + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/defs.h linux-2.6.30.4/drivers/block/tffs/defs.h --- linux-2.6.30.4-orig/drivers/block/tffs/defs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/defs.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,238 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/DocDriver/TrueFFS BD/src/defs.h-arc $ + * + * Rev 1.6 Oct 22 2007 11:34:48 einat.avidan + * update copyrights header + * + * Rev 1.5 Oct 11 2007 18:47:46 Einat.Avidan + * remove unused or duplicated definitions + * + * Rev 1.4 Jul 01 2007 13:47:28 einat.avidan + * bug fix: SCR 2964 compilation flag FL_VERIFY_WRITE should exclude \ include code for write verification + * + * Rev 1.3 Oct 09 2006 14:05:18 yaniv.iarovici + * Removed legacy devices related code and definitions + * + * Rev 1.2 Sep 11 2006 13:45:12 yaniv.iarovici + * Legal header added + * + * Rev 1.1 Aug 22 2006 13:22:40 Yaniv.Iarovici + * 1) Remove decleration fo 'void flInitGlobalVars(void)' + * 2) Add 'extern "c"' on: + * - flIdentifyFlash() external definition + * - flHandleConversionTable[] external definition + * - _flInit() definition + * + * Rev 1.0 Aug 08 2006 15:47:24 Polina.Marimont + * Initial revision. + */ + +#ifndef _DEFS_H +#define _DEFS_H + + +/*=============================================================*/ +/* from flsocket.h */ +#include "flbuffer.h" + +#define ATTRIBUTE_SPACE_MAPPED 0x8000 +#define UNDEFINED_MAPPING 0x7fff + + +typedef enum {PowerOff, PowerGoingOff, PowerOn} PowerState; + +extern FLByte noOfSockets; /* No. of drives actually registered */ + +typedef struct tSocket FLSocket; +/*=============================================================*/ + +/*=============================================================*/ +/* from _flsoc.h */ +struct tSocket { + unsigned volNo; /* Volume no. of socket */ + + PowerState DPDState; /* Actual DPD state */ + FLBoolean remapped; /* set to TRUE whenever the socket window is moved */ + + void (*powerOnCallback)(void *flash); /* Notification routine for Vcc on */ + void * flash; /* Flash object for callback */ + + struct { /* Window state */ + unsigned int baseAddress; /* Physical base as a 4K page */ + unsigned int currentPage; /* Our current window page mapping */ + void FAR0 * base; /* Pointer to window base */ + FLSDword size; /* Window size (must by power of 2) */ + unsigned speed; /* in nsec. */ + unsigned busWidth; /* 8 or 16 bits */ + } window; + FLBoolean (*cardDetected)(FLSocket * pVol); + void (*VccOn)(FLSocket * pVol); + void (*VccOff)(FLSocket * pVol); + FLStatus (*initSocket)(FLSocket * pVol); + void (*setWindow)(FLSocket * pVol); + void (*setMappingContext)(FLSocket * pVol, unsigned page); + FLBoolean (*getAndClearCardChangeIndicator)(FLSocket * pVol); + FLBoolean (*writeProtected)(FLSocket * pVol); + void (*updateSocketParams)(FLSocket * pVol, void FAR1 *params); +#ifdef FL_EXIT + void (*freeSocket)(FLSocket * pVol); +#endif +}; + + +/* See interface documentation of functions in socket.c */ + +extern FLStatus updateSocketParameters(FLSocket *, void FAR1 *); + + +extern FLSocket* flSocketOf(unsigned volNo); + + +/*=============================================================*/ + +/*=============================================================*/ +/* from flflash.h */ + +/* Some useful types for mapped Flash locations */ + +typedef volatile FLByte FAR0 * FlashPTR; +typedef volatile unsigned short int FAR0 * FlashWPTR; +typedef volatile FLDword FAR0 * FlashDPTR; +typedef FLWord FlashType; /* JEDEC id */ +typedef volatile FLByte FAR0* NDOC2window; + +typedef FLByte Reg8bitType; +typedef FLWord Reg16bitType; + + +/* Media types */ +#define H3_TYPE 15 + +/* protection specific defintions */ +#define PROTECTION_KEY_LENGTH 8 /* Size of protection key in bytes */ +#define DEFAULT_KEY "00000000" + + +/****************************/ +/* Special services API */ +/****************************/ + + +/* Flash array identification structure */ +typedef struct tFlash FLFlash; /* Forward definition */ + +/*=============================================================*/ + + +/*=============================================================*/ +/* from _flflash.h */ + +struct tFlash { + FLBoolean wasIdentified; + FlashType type; + FlashType subType; + FLByte mediaType; + FLDword busAccessType; + FLByte if_cfg; + FLByte bBusType; + FLWord flags; + void * mtdVars; + FLSocket * socket; + NDOC2window win; + void (*setPowerOnCallback)(FLFlash *); + FLStatus (*flashRead)(FLFlash *); + FLStatus (*setCallBack)(FLFlash *); + FLStatus (*dismount)(FLFlash *); + FLStatus (*prepareForPowerChanges) (FLFlash *,FLByte) ; + FLStatus (*clearCallBack)(FLFlash *); + FLStatus (*enterDeepPowerDownMode)(FLFlash *,FLWord state); + +#ifndef FL_NO_USE_FUNC + FLMemWindowSize FAR1* memWindowSize; /* Doc memory window size */ + FLMemRead FAR1* memRead; /* Doc memory read routine */ + FLMemWrite FAR1* memWrite; /* Doc memory write routine */ + FLMemSet FAR1* memSet; /* Doc memory set routine */ + FLMemRead8bit FAR1* memRead8bit; /* Doc memory 8 bit read routine */ + FLMemWrite8bit FAR1* memWrite8bit; /* Doc memory 8 bit write routine */ + FLMemRead16bit FAR1* memRead16bit; /* Doc memory 16 bit read routine */ + FLMemWrite16bit FAR1* memWrite16bit; /* Doc memory 16 bit write routine */ + FLMemSetGetMode FAR1* memSetGetMode; /* Interleave change event - */ + /* call back to plant new routines */ +#endif /* FL_NO_USE_FUNC */ +}; + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +extern TFFS_DLL_API FLFlash * NAMING_CONVENTION flFlashOf(FLByte volNo); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +/*=============================================================*/ + + +/*=============================================================*/ +/*=== from nandefs.h */ + +/*=============================================================*/ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ +FLStatus _flInit(void); +void flInitGlobalVars(void); +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /*_DEFS_H*/ + + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/docbdk.h linux-2.6.30.4/drivers/block/tffs/docbdk.h --- linux-2.6.30.4-orig/drivers/block/tffs/docbdk.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/docbdk.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,550 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/3/bddoc/src/docbdk.h-arc $ + * + * Rev 1.8 Oct 22 2007 11:34:48 einat.avidan + * update copyrights header + * + * Rev 1.7 Sep 11 2006 13:45:12 yaniv.iarovici + * Legal header added + * + * Rev 1.6 Aug 09 2006 16:52:46 Polina.Marimont + * initial for DOC Driver 1.0 + * + */ + +/************************************************************************/ +/* Caution: The BDK_ACCESS compilation flag is for M-SYSTEMS internal */ +/* use ONLY. This flag is used by M-SYSTEMS drivers and */ +/* therfore it is SHOULD NOT be used by this package */ +/************************************************************************/ + +/***************************************************************************** +* File Header * +* ----------- * +* Name : docbdk.h * +* * +* Description : This file contains the binary partition defintions , data * +* structures and function prototypes. * +* * +* Note : The file exports 2 interfaces each under its own compilation flag: * +* * +* BDK package - Standalone package that exports routines for binary * +* partitions handling(MTD_STANDALONE compilation flag). * +* OSAK module - Separated module of the OSAK package that exports a * +* common entry point to the same routines. (BDK_ACCESS * +* compilation flag). * +* * +* Warning : Do not use this file with the BDK_ACCESS compilation flag unless * +* you own the full OSAK package. * +*****************************************************************************/ + +#ifndef DOCBDK_H +#define DOCBDK_H +/*---------------------------------------------------------------------*/ +/* Include the proper header files. */ +/*---------------------------------------------------------------------*/ + +#include "flcommon.h" + +#ifndef MTD_STANDALONE +#ifdef BDK_ACCESS +#include "flstruct.h" +#endif /* BDK_ACCESS */ +#endif /* MTD_STANDALONE */ + +/* Use the define bellow to set the size of the page buffer used by the BDK */ +#ifndef BDK_SECTORS_PER_PAGE +#define BDK_SECTORS_PER_PAGE (8L /* 2KB PAGE */) +#endif /* BDK_SECTORS_PER_PAGE */ + +#ifndef BDK_SECTORS_PER_WRITE +#define BDK_SECTORS_PER_WRITE (4L/*Planes*/*BDK_SECTORS_PER_PAGE/*Sectors per page*/*2/*MLC*/) +#endif /* BDK_SECTORS_PER_WRITE */ + + +/* BDK specific flag area */ +#define ERASE_BEFORE_WRITE 8 +#define BDK_SPARE_BLOCKS_SIGN "S4BB" /* Must be the same as BINARY_SPARE_BLOCKS_SIGN (FLFORMAT.H) */ + + +/*----------------------------------------------------------------------*/ +/* b d k F i n d D i s k O n C h i p */ +/* */ +/* Find and identify DiskOnChip device if installed in the system. The */ +/*search address are set by the flregisterDOCXXXSOC call in flcustom.c */ +/*file. */ +/* */ +/* */ +/* Parameters: */ +/* docAddress : Pointer to return value of DiskOnChip */ +/* address (if found). */ +/* docSize : Pointer to return value of DiskOnChip */ +/* address window size (if found). */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success (DiskOnChip found) */ +/* otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkFindDiskOnChip (CardAddress FAR2 *docAddress, + FLDword FAR2 *docSize ); +/*----------------------------------------------------------------------*/ +/* b d k I n i t */ +/* */ +/* Initialize the BDK SW package. This function is normaly called */ +/*automatically by the first call to the BDK package functions. */ +/* */ +/* Parameters: */ +/* None. */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +void bdkInit( void ); + +#ifdef FL_EXIT +/*----------------------------------------------------------------------*/ +/* b d k E X i t */ +/* */ +/* Reset the BDK SW package. This function is normaly called as the last*/ +/*reference to the BDK package, providing clean exit and clearing all */ +/*allocated memory. */ +/* */ +/* Parameters: */ +/* None. */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +void bdkExit (void); +#endif /* FL_EXIT */ + +/*----------------------------------------------------------------------*/ +/* b d k S e t B o o t P a r t i t i o n N o */ +/* */ +/* Set the current BDK partition in use. The default partition is */ +/*partition 0. For operation on other partitions, this routine should be*/ +/*called prior to actual command. The partition set is valid until the */ +/*next time this function is called. */ +/* */ +/* Parameters: */ +/* partitionNo : partition number to be access next. */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkSetBootPartitionNo (FLByte partitionNo); + +/*----------------------------------------------------------------------*/ +/* b d k G e t B o o t P a r t i t i o n I n f o */ +/* */ +/* Get information regarding the actual size and used size of a binary */ +/*(sub) partition. */ +/* */ +/* Parameters: */ +/* startUnit : First block containing data (usually 0) */ +/* partitionSize : Pointer to output value of full */ +/* sub partition size. */ +/* realPartitionSize : Pointer to return value of used size. */ +/* unitSize : Pointer to return value of unit size. */ +/* signature : Signature of retrieved sub partition. */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkGetBootPartitionInfo (FLWord startUnit, + FLDword FAR2 *partitionSize, + FLDword FAR2 *realPartitionSize, + FLDword FAR2 *unitSize, + FLByte FAR2 *signature); + +/*----------------------------------------------------------------------*/ +/* b d k C o p y B o o t A r e a */ +/* */ +/* Copy data from binary partition to RAM */ +/* */ +/* Parameters: */ +/* startAddressPtr : Pointer to start RAM address */ +/* wStartUnit : No' of first block in partition(usualy 0).*/ +/* dwAreaLen : Length of read area. */ +/* bCheckSumPtr : Pointer to output chksum calculation. */ +/* signPtr : Signature of retrieved sub partition. */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkCopyBootArea (FLByte FAR1 *startAddressPtr, + FLWord wStartUnit, + FLDword dwAreaLen, + FLByte FAR2 *bCheckSumPtr, + FLByte FAR2 *signPtr); + +/*----------------------------------------------------------------------*/ +/* b d k C o p y B o o t A r e a I n i t */ +/* */ +/* Initialize read process from BDK area. This routine must be called */ +/*prior to any series of bdkCopyBootAreaBlock calls. The areaLen set by */ +/*this routine must be total len of all calls to following */ +/*bdkCopyBootAreaBlock calls. */ +/* */ +/* Parameters: */ +/* startUnit : first unit to read (must contain data). */ +/* areaLen : length of bdk are to be read. */ +/* signature : Signature of retrieved sub partition. */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkCopyBootAreaInit (FLWord startUnit, + FLDword areaLen, + FLByte FAR2 *signature); + +/*----------------------------------------------------------------------*/ +/* b d k C o p y B o o t A r e a B l o c k */ +/* */ +/* read the next chunk of data from BDK area. This routine call must */ +/*follow a call to bdkCopyBootAreaInit and cannot be used without */ +/*proper init call. */ +/* */ +/* Parameters: */ +/* buf : Buffer where to read the data. */ +/* bufferLen : Length of current read buffer. */ +/* checkSum : Pointer for output ChkSum calculation of */ +/* read data. */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkCopyBootAreaBlock (FLByte FAR1 *buf , + FLDword bufferLen, + FLByte FAR2 *checkSum); + +/*----------------------------------------------------------------------*/ +/* b d k U p d a t e B o o t A r e a I n i t */ +/* */ +/* XXXX */ +/* XXXX */ +/* XXXX */ +/* */ +/* Parameters: */ +/* xx : xxxx */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkUpdateBootAreaInit (FLWord startUnit, + FLDword areaLen, + FLByte updateFlag, + FLByte FAR2 *signature ); + +/*----------------------------------------------------------------------*/ +/* x */ +/* */ +/* XXXX */ +/* XXXX */ +/* XXXX */ +/* */ +/* Parameters: */ +/* xx : xxxx */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkUpdateBootAreaBlock (FLByte FAR1 *buf , + FLDword bufferLen ); + +/*----------------------------------------------------------------------*/ +/* x */ +/* */ +/* XXXX */ +/* XXXX */ +/* XXXX */ +/* */ +/* Parameters: */ +/* xx : xxxx */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkGetProtectionType (FLWord * protectionType); + +/*----------------------------------------------------------------------*/ +/* x */ +/* */ +/* XXXX */ +/* XXXX */ +/* XXXX */ +/* */ +/* Parameters: */ +/* xx : xxxx */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkInsertKey (FLByte FAR1* key); + +/*----------------------------------------------------------------------*/ +/* x */ +/* */ +/* XXXX */ +/* XXXX */ +/* XXXX */ +/* */ +/* Parameters: */ +/* xx : xxxx */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkRemoveKey (void); + +/*----------------------------------------------------------------------*/ +/* x */ +/* */ +/* XXXX */ +/* XXXX */ +/* XXXX */ +/* */ +/* Parameters: */ +/* xx : xxxx */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkStickyLock (void); + +/*----------------------------------------------------------------------*/ +/* x */ +/* */ +/* XXXX */ +/* XXXX */ +/* XXXX */ +/* */ +/* Parameters: */ +/* xx : xxxx */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkLockEnable (FLByte enable); + +/*----------------------------------------------------------------------*/ +/* x */ +/* */ +/* XXXX */ +/* XXXX */ +/* XXXX */ +/* */ +/* Parameters: */ +/* xx : xxxx */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkChangeKey (FLByte FAR1* key); +/*----------------------------------------------------------------------*/ +/* x */ +/* */ +/* XXXX */ +/* XXXX */ +/* XXXX */ +/* */ +/* Parameters: */ +/* xx : xxxx */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkSetProtectionType (FLWord newType); + +/*----------------------------------------------------------------------*/ +/* x */ +/* */ +/* XXXX */ +/* XXXX */ +/* XXXX */ +/* */ +/* Parameters: */ +/* xx : xxxx */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkCreateBootArea (FLWord noOfBlocks, + FLByte FAR2 * oldSign, + FLByte FAR2 * newSign); + +/*----------------------------------------------------------------------*/ +/* x */ +/* */ +/* XXXX */ +/* XXXX */ +/* XXXX */ +/* */ +/* Parameters: */ +/* xx : xxxx */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkEraseBootArea (FLWord startUnit, + FLWord noOfBlocks, + FLByte FAR2 * signature); + +/*----------------------------------------------------------------------*/ +/* x */ +/* */ +/* XXXX */ +/* XXXX */ +/* XXXX */ +/* */ +/* Parameters: */ +/* xx : xxxx */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkGetUniqueID(FLByte FAR1* buf); + +/*----------------------------------------------------------------------*/ +/* x */ +/* */ +/* XXXX */ +/* XXXX */ +/* XXXX */ +/* */ +/* Parameters: */ +/* xx : xxxx */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkReadOtp(FLWord offset,FLByte FAR1 * buffer,FLWord length); + +/*----------------------------------------------------------------------*/ +/* x */ +/* */ +/* XXXX */ +/* XXXX */ +/* XXXX */ +/* */ +/* Parameters: */ +/* xx : xxxx */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkWriteAndLockOtp(const FLByte FAR1 * buffer,FLWord length); + +/*----------------------------------------------------------------------*/ +/* x */ +/* */ +/* XXXX */ +/* XXXX */ +/* XXXX */ +/* */ +/* Parameters: */ +/* xx : xxxx */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkGetOtpSize(FLDword FAR2* sectionSize, FLDword FAR2* usedSize, + FLWord FAR2* locked); + +/*----------------------------------------------------------------------*/ +/* x */ +/* */ +/* XXXX */ +/* XXXX */ +/* XXXX */ +/* */ +/* Parameters: */ +/* xx : xxxx */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkWriteIPL (FLByte FAR1 * buf , FLDword bufLen , FLDword offset,FLDword flags); + +/*----------------------------------------------------------------------*/ +/* */ +/* */ +/* XXXX */ +/* XXXX */ +/* XXXX */ +/* */ +/* Parameters: */ +/* xx : xxxx */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkCopyBootAreaFile ( FLSByte FAR2 *fname, + FLWord startUnit, + FLDword areaLen, + FLByte FAR2 *checkSum, + FLByte FAR2 *signature ); + +/*----------------------------------------------------------------------*/ +/* */ +/* */ +/* XXXX */ +/* XXXX */ +/* XXXX */ +/* */ +/* Parameters: */ +/* xx : xxxx */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkUpdateBootAreaFile(FLSByte FAR2 *fname, FLWord startUnit, + FLDword areaLen, FLByte FAR2 *signature); + +#endif /* DOCBDK_H */ + + + + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/docdrv.c linux-2.6.30.4/drivers/block/tffs/docdrv.c --- linux-2.6.30.4-orig/drivers/block/tffs/docdrv.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/docdrv.c 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,470 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/DocDriver/TrueFFS BD/src/docdrv.c-arc $ + * + * Rev 1.14 Feb 03 2008 23:48:34 Yuli.Izrailov + * Bug fix: dochGotDiskUserAttributes wasn't nullified on flExit. + * Added Quick Init support. + * + * Rev 1.12 Oct 22 2007 11:34:48 einat.avidan + * update copyrights header + * + * Rev 1.11 Sep 04 2007 15:26:44 einat.avidan + * add printouts + * + * Rev 1.10 Jul 01 2007 13:47:28 einat.avidan + * bug fix: SCR 2964 compilation flag FL_VERIFY_WRITE should exclude \ include code for write verification + * + * Rev 1.9 Feb 28 2007 10:32:00 einat.avidan + * CX tools support + * + * Rev 1.8 Feb 15 2007 17:40:52 Einat.Avidan + * Add support in edge\level and polarity within FL_DMA_INIT compilation flag + * + * Rev 1.7 Nov 13 2006 15:13:48 Yaniv.Iarovici + * Added environment variable - 'FL_DISABLE_MEMCPY'. + * + * Rev 1.6 Oct 30 2006 15:50:16 yaniv.iarovici + * Add call to flDOCHIdentifyDiskOnChipDevice() after flInit() is completed + * for updating actual number of partitions. + * + * Rev 1.5 Sep 11 2006 13:45:14 yaniv.iarovici + * Legal header added + * + * Rev 1.4 Aug 22 2006 13:22:54 Yaniv.Iarovici + * Bug fix: 'FL_DMA_HW_ENABLED' was NOT treated as bit but as a value in flInit(). + * + * Rev 1.3 Aug 16 2006 08:43:26 Yaniv.Iarovici + * Add support for Environment Variable: 'FL_SET_TRANSFER_MODE' - Controls DRQ size + * + * Rev 1.2 Aug 10 2006 10:39:48 Polina.Marimont + * reinit fix + * + * Rev 1.1 Aug 10 2006 10:37:14 Polina.Marimont + * bug fix - avoid initializing twice + * + * Rev 1.0 Aug 08 2006 15:47:22 Polina.Marimont + * Initial revision. + */ +#include "flchkdef.h" +#include "flcommon.h" +#include "flstdcmp.h" +#include "blockdev.h" +#include "tffs_api.h" +#include "doch_api.h" +#include "doch_ata.h" +#include "bddefs.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +FLStatus bdSetBusy(Volume * pVol, FLBoolean state, FLByte partition); + +extern FLBoolean dochBdCallWasCalled; +extern FLBoolean dochGotDiskUserAttributes; +#ifndef DOCH_USE_FUNC +FLFlash * DOCHFlash; +#endif /* DOCH_USE_FUNC */ + + +bdCallType bdCall = bdCallTFFSToDOCH; +static FLBoolean fDocDriverInitDone = FALSE; + + +extern FLBoolean flPreventMemcpy; + +#ifdef CX_ATA_SNIFFER + FILE * ataLogFile ; +#endif /*CX_ATA_SNIFFER*/ + +/***********************************************************************************/ +/* Function name : NAMING_CONVENTION flInit */ +/* Description : */ +/* Return type : TFFS_DLL_API FLStatus */ +/***********************************************************************************/ +TFFS_DLL_API FLStatus NAMING_CONVENTION flInit() +{ +#if (!defined(DOCH_USE_FUNC)) && (!defined (FL_NO_USE_FUNC)) + FLStatus flStatus; + FLDword dwBusConfig = flBusConfig[0]; +#endif /*!DOCH_USE_FUNC && !FL_NO_USE_FUNC*/ + DOCH_Error status_HDOC = DOCH_OK; + DOCH_DeviceInfo tempDOCDI; + IOreq ioreq; + DOCH_Socket* pdev; + DOCH_get_socket(pdev, 0); + +#ifdef CX_ATA_SNIFFER + ataLogFile=fopen("atalog.bin","wb"); + if (! ataLogFile) + { + DBG_PRINT_FLOW(FLZONE_ABS, "\r\n*** Cannot Create atalog file in flInit() ***\r\n\n\n"); + return DOCH_ATA_ERROR_ABORT; + } +#endif /*CX_ATA_SNIFFER*/ + + if( fDocDriverInitDone == TRUE ) + return flOK; + + _flInit(); + + flSysfunInit(); + + DBG_PRINT_FLOW(FLZONE_ABS, "Searching for H3 device... \r\n"); + +#ifndef DOCH_USE_FUNC + /* Initialize DOCHFlash and redirect to regular MTD access layer */ + DOCHFlash = flFlashOf(0); +#ifndef FL_NO_USE_FUNC + dwBusConfig |= FL_16BIT_DOC_ACCESS ; + dwBusConfig |= FL_16BIT_FLASH_ACCESS ; + dwBusConfig |= FL_BUS_HAS_16BIT_ACCESS; + flStatus = setBusTypeOfFlash(DOCHFlash,dwBusConfig); + if(flStatus != flOK) + return flStatus; +#endif /* FL_NO_USE_FUNC */ +#endif /* DOCH_USE_FUNC */ + + status_HDOC = DochSDKInit(); + if(status_HDOC == DOCH_OK) /*DOCH Device*/ + { + DBG_PRINT_FLOW(FLZONE_ABS, "H3 Device found !!! \r\n\n"); + bdCall = bdCallTFFSToDOCH; +#ifdef FL_DMA_INIT + { + IOreq myIoreq; + FLDword ctrl; + FLByte bDmaInit = FL_DMA_INIT(0); + if( (bDmaInit & FL_DMA_HW_ENABLED) == FL_DMA_HW_ENABLED ) /*if DMA enabled by default -> set this to SA SDK*/ + { + tffsset(&myIoreq, 0, sizeof(myIoreq)); + myIoreq.irFlags = DOCH_DMA_ENABLE; + myIoreq.irLength = TRUE; + status_HDOC = flDOCHConfigHW(&myIoreq); + if( status_HDOC!=DOCH_OK ) + { + DBG_PRINT_FLOW_PRM(FLZONE_ABS, (FLTXT("Fail to enable DMA with status %d \r\n"),status_HDOC)); + } + } + tffsset(&myIoreq, 0, sizeof(myIoreq)); + myIoreq.irFlags = DOCH_DMA_CTRL; + ctrl = ((DOCH_DMA_PULSE_WIDTH)<<4) | DOCH_DMA_REQ_POL_LOW; + if (bDmaInit & FL_DMA_REQ_EDGE) + ctrl |= DOCH_DMA_REQ_EDGE; + if (bDmaInit & FL_NEGATED_0_ASSERTED_1) + ctrl &= ~DOCH_DMA_REQ_POL_LOW; + myIoreq.irLength = ctrl; + status_HDOC = flDOCHConfigHW(&myIoreq); + if( status_HDOC!=DOCH_OK ) + { + DBG_PRINT_FLOW_PRM(FLZONE_ABS, (FLTXT("Fail to set DMA control register with status %d \r\n"),status_HDOC)); + } + } +#endif /*FL_DMA_INIT*/ + + /* Update number of partitions*/ + tffsset(&ioreq, 0, sizeof(ioreq)); + ioreq.irData = &tempDOCDI; + status_HDOC = flDOCHIdentifyDiskOnChipDevice(&ioreq); + pdev->wTotalNumOfPartitions = tempDOCDI.wTotalNumOfPartitions; + + if( status_HDOC==DOCH_OK ) + fDocDriverInitDone = TRUE; + + return (status_HDOC==DOCH_OK)?flOK:((status_HDOC==DOCH_DiskNotFound)?flAdapterNotFound:flGeneralFailure); + } + + DBG_PRINT_ERR(FLZONE_ABS, "flInit(): failed to find mDoc! \r\n\n"); + DBG_PRINT_FLOW(FLZONE_ABS, "\r\n*** Exiting flInit() ***\r\n\n\n"); + + return flAdapterNotFound; +}/* flInit() */ + +#ifdef FL_EXIT + +/***********************************************************************************/ +/* Function name : NAMING_CONVENTION flExit*/ +/* Description : */ +/* Return type : TFFS_DLL_API void */ +/***********************************************************************************/ +TFFS_DLL_API void NAMING_CONVENTION flExit() +{ + tffsApiExit(); + dochBdCallWasCalled = FALSE; + dochGotDiskUserAttributes = FALSE; + fDocDriverInitDone = FALSE; +#ifdef CX_ATA_SNIFFER + fclose(ataLogFile); +#endif /*CX_ATA_SNIFFER*/ +}/*flExit()*/ +#endif /*FL_EXIT*/ + +#ifdef FL_ENVIRONMENT_VARS + +/***********************************************************************************/ +/* Function name : NAMING_CONVENTION flSetEnvVolume */ +/* Description : */ +/* Return type : TFFS_DLL_API FLStatus */ +/* Argument : FLEnvVars variableType */ +/* Argument : FLByte socket */ +/* Argument : FLByte volume */ +/* Argument : FLDword value */ +/* Argument : FLDword FAR2 *prevValue */ +/***********************************************************************************/ +TFFS_DLL_API FLStatus NAMING_CONVENTION flSetEnvVolume(FLEnvVars variableType, FLByte socket, FLByte volume, + FLDword value, FLDword FAR2 *prevValue) +{ + IOreq ioreq; + + ioreq.irHandle = socket + (volume << 4); + /*For utilities which uses env vars on legacy devices and not needed for H3*/ + if ((variableType == FL_DEBUG_MODES) || + (variableType == FL_SUSPEND_MODE) || + (variableType == FL_DIMAGE_CFG)) + return flOK; + + if(variableType == FL_SET_TRANSFER_MODE) + { + tffsset(&ioreq, 0, sizeof(ioreq)); + /*Fill ioreq structure according to flDOCHSetDataTransferMode API*/ + /*Single sector transfer mode*/ + if(value == 1) + { + ioreq.irCount = DOCH_DATA_XFER_MODE_SINGLE; + } + /*Multi-sector transfer mode*/ + else + { + ioreq.irCount = DOCH_DATA_XFER_MODE_MULT; + ioreq.irLength = value; + } + + /*Set requested Transfer Mode and Length*/ + if (flDOCHSetDataTransferMode(&ioreq) == DOCH_OK) + return flOK; + + /*If the operation failed*/ + return flFeatureNotSupported; + } + else if (variableType == FL_ENV_ATA_DEBUG) + ioreq.irFlags = DOCH_ENV_ATA_DEBUG; + else if(variableType == FL_DISABLE_MEMCPY) + flPreventMemcpy = value; + else + { + switch(variableType) + { +#ifdef FL_VERIFY_WRITE + case FL_VERIFY_WRITE_BDTL: + case FL_VERIFY_WRITE_BINARY: + case FL_VERIFY_WRITE_OTHER: + ioreq.irFlags = DOCH_ENV_VERIFY_WRITE; + break; +#endif /*FL_VERIFY_WRITE*/ + +#ifdef FL_UTILS_QUICK_INIT + case FL_ENV_QUICK_INIT: + ioreq.irFlags = DOCH_ENV_QUICK_INIT; + + /*This env var have to be set before flInit() + *Try to protect on wrong use*/ + fDocDriverInitDone = FALSE; /*flInit() direct call*/ + dochBdCallWasCalled = FALSE; /*flInit() call through bdCall*/ + break; +#endif /*FL_UTILS_QUICK_INIT*/ + +#if (!defined(FL_NO_USE_FUNC) || defined(FL_BD_AUTO_DPD_MODE)) + case FL_SET_AUTO_DPD_MODE: +#ifndef DOCH_AUTO_DPD_BY_HOST + case FL_SET_ACTIVE_DPD_MODE: + case FL_SET_INACTIVE_DPD_MODE: + case FL_SET_TIMEOUT_DPD: +#endif /*DOCH_AUTO_DPD_BY_HOST*/ + return tffsApiSetAutoDpd(variableType, (FLSDword)socket, value, prevValue); +#endif /*(!defined(FL_NO_USE_FUNC) || defined (FL_BD_AUTO_DPD_MODE))*/ + default: + ioreq.irFlags = 0; + }/*switch*/ + } + ioreq.irLength = value; + if (flDOCHSetEnvVar(&ioreq) == DOCH_OK) + return flOK; + return flFeatureNotSupported; +}/*flSetEnvVolume()*/ + + +/***********************************************************************************/ +/* Function name : NAMING_CONVENTION flSetEnvSocket*/ +/* Description : */ +/* Return type : TFFS_DLL_API FLStatus */ +/* Argument : FLEnvVars variableType*/ +/* Argument : FLByte socket*/ +/* Argument : LDword value*/ +/* Argument : FLDword FAR2 *prevValue*/ +/***********************************************************************************/ +TFFS_DLL_API FLStatus NAMING_CONVENTION flSetEnvSocket(FLEnvVars variableType, FLByte socket, + FLDword value, FLDword FAR2 *prevValue) +{ + return flSetEnvVolume(variableType, socket, 0, value, prevValue); +}/*flSetEnvSocket()*/ + + +/***********************************************************************************/ +/* Function name : NAMING_CONVENTION flSetEnvAll */ +/* Description : */ +/* Return type : TFFS_DLL_API FLStatus */ +/* Argument : FLEnvVars variableType */ +/* Argument : FLDword value */ +/* Argument : FLDword FAR2 *prevValue */ +/***********************************************************************************/ +TFFS_DLL_API FLStatus NAMING_CONVENTION flSetEnvAll( FLEnvVars variableType,FLDword value, + FLDword FAR2 *prevValue) +{ + return flSetEnvVolume(variableType, 0, 0, value, prevValue); +}/*flSetEnvAll*/ +#endif /*FL_ENVIRONMENT_VARS*/ + +#ifndef FL_NO_USE_FUNC + + +/***********************************************************************************/ +/* Function name : NAMING_CONVENTION flGetDocBusRoutine*/ +/* Description : */ +/* Return type : TFFS_DLL_API FLStatus */ +/* Argument : FLByte socket */ +/* Argument : FLAccessStruct FAR1 * structPtr */ +/***********************************************************************************/ +TFFS_DLL_API FLStatus NAMING_CONVENTION flGetDocBusRoutine(FLByte socket, FLAccessStruct FAR1 * structPtr) +{ + FLFlash* flash; + + /* Arg sanity check */ +#ifndef FL_SKIP_ARGS_CHECK + if (socket >= FL_SOCKETS) + { + DBG_PRINT_ERR(FLZONE_BLKDEV,"ERROR - Change FL_SOCKETS definition in flcustom.h to support that many sockets.\r\n"); + return flFeatureNotSupported; + } + if(structPtr == NULL) + { + DBG_PRINT_ERR(FLZONE_BLKDEV,"ERROR - structPtr argument is NULL.\r\n"); + return flBadParameter; + } +#endif /* FL_SKIP_ARGS_CHECK */ + + /* Make sure global variables are initialized to their default values */ + flInitGlobalVars(); + + flash = flFlashOf(socket); + + structPtr->memWindowSize = flash->memWindowSize; + structPtr->memRead = flash->memRead; + structPtr->memWrite = flash->memWrite; + structPtr->memSet = flash->memSet; + structPtr->memRead8bit = flash->memRead8bit; + structPtr->memRead16bit = flash->memRead16bit; + structPtr->memWrite8bit = flash->memWrite8bit; + structPtr->memWrite16bit = flash->memWrite16bit; + structPtr->memSetGetMode = flash->memSetGetMode; + structPtr->access = flBusConfig[socket]; + + return flOK; +}/*flGetDocBusRoutine()*/ + + +/***********************************************************************************/ +/* Function name : NAMING_CONVENTION flSetDocBusRoutine*/ +/* Description : */ +/* Return type : TFFS_DLL_API FLStatus */ +/* Argument : FLByte socket*/ +/* Argument : FLAccessStruct FAR1 * structPtr*/ +/***********************************************************************************/ +TFFS_DLL_API FLStatus NAMING_CONVENTION flSetDocBusRoutine(FLByte socket,FLAccessStruct FAR1 * structPtr) +{ + FLFlash* flash; + + /* Arg sanity check */ +#ifndef FL_SKIP_ARGS_CHECK + if (socket >= FL_SOCKETS) + { + DBG_PRINT_ERR(FLZONE_BLKDEV,"ERROR - Change FL_SOCKETS definition in flcustom.h to support that many sockets.\r\n"); + return flFeatureNotSupported; + } + if(structPtr == NULL) + { + DBG_PRINT_ERR(FLZONE_BLKDEV,"ERROR - structPtr argument is NULL.\r\n"); + return flBadParameter; + } +#endif /* FL_SKIP_ARGS_CHECK */ + + /* Make sure global variables are initialized to their default values */ + flInitGlobalVars(); + + flash = flFlashOf(socket); + + flash->memWindowSize = structPtr->memWindowSize; + flash->memRead = structPtr->memRead; + flash->memWrite = structPtr->memWrite; + flash->memSet = structPtr->memSet; + flash->memRead8bit = structPtr->memRead8bit; + flash->memRead16bit = structPtr->memRead16bit; + flash->memWrite8bit = structPtr->memWrite8bit; + flash->memWrite16bit = structPtr->memWrite16bit; + flash->memSetGetMode = structPtr->memSetGetMode; + flBusConfig[socket] = FL_ACCESS_USER_DEFINED; + return flOK; +}/*flSetDocBusRoutine*/ + +#endif /*FL_NO_USE_FUNC*/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +/* ----------------------------------------------------------------------------------- */ + + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/doch_api.c linux-2.6.30.4/drivers/block/tffs/doch_api.c --- linux-2.6.30.4-orig/drivers/block/tffs/doch_api.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/doch_api.c 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,9166 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Test for 7.x/src/H3/doch_api.c-arc $ + * + * Rev 1.83 Jan 31 2008 21:17:16 Yuli.Izrailov + * Added Quick Init support + * + * Rev 1.82 Dec 26 2007 10:12:52 einat.avidan + * add flow printout for verify write + * dochATAReset() - update delay required + * doch_reset() does not include waiting before reset + * doch_reset() fixed bug (waiting for both floors to be ready after reset) + * + * Rev 1.81 Dec 16 2007 11:35:20 einat.avidan + * add debug printout + * + * Rev 1.80 Dec 11 2007 12:26:08 einat.avidan + * init sequence and DOCHConfigHW: change parameters of internal functions + * + * Rev 1.79 Dec 04 2007 17:54:20 einat.avidan + * Remove flDOCHWipeSectorsByWriting + * Change algorithm of DOCHWipeSectors and for AUTO_WIPE_SECTORS + * Bug fix: verify write on cascaded device. + * Bug fix: DochRecoverFromPowerLoss + * + * Rev 1.78 Oct 30 2007 16:13:54 einat.avidan + * add new function flDOCHWipeSectorsByWriting + * bug fix: DOCHDeletePartitions migth access second floor even + * if it does not exist. + * DOCHAddPartition: add support in fast area in cascaded configuration + * add new function DOCHWipeSectorsByWriting + * + * Rev 1.77 Oct 23 2007 15:32:10 einat.avidan + * fix compilation warnings + * + * Rev 1.76 Oct 23 2007 12:27:52 einat.avidan + * optimization: delay after setting head register only + * when switching floors + * + * Rev 1.75 Oct 22 2007 11:34:48 einat.avidan + * update copyrights header + * + * Rev 1.74 Oct 21 2007 10:27:32 Einat.Avidan + * bug fix: reported fast area on spanned partition + * set LBA bit on device head register + * fix compilation warnings + * + * Rev 1.73 Oct 11 2007 18:48:02 Einat.Avidan + * Replace global Boolean pattern with pattern in size of + * byte instead of dWord + * fix printouts + * add compilation flags for SOTP and SLPP + * support cascaded configuration: add delay after device switch + * Interrupts are enabeled\ disabeled in the ATA level instead of API level + * DOCHReadPartitionSectorsSingleFloor was added + * DOCHWritePartitionSectorsSingleFloor was added + * in every write to drive head register set LBA bit. + * + * Rev 1.72 Sep 04 2007 15:28:18 einat.avidan + * fix printouts + * avoid locking OTP when passed length (in sectors) is zero + * + * Rev 1.71 Jul 01 2007 13:47:28 einat.avidan + * bug fix: SCR 2964 compilation flag FL_VERIFY_WRITE should exclude \ include code for write verification + * + * Rev 1.70 Mar 22 2007 17:12:10 einat.avidan + * add SOTP + * + * Rev 1.69 Mar 13 2007 13:47:20 einat.avidan + * add support for SLPP + * + * Rev 1.68 Mar 11 2007 16:28:46 einat.avidan + * bug fix: update number of partitions when spanned partition that does not cover whole media was added + * bug fix: internal API flDOCHAtaReset may cause confusion in the XIP window identification. + * + * Rev 1.67 Feb 28 2007 10:32:28 einat.avidan + * bug fix: scr 2255 Compatibility on Big\Little Endian + * bug fix: during flInit device head register was changed to Slave, even if MAX_ATA_DEVICES is 1. + * may cause a bug during boot. + * bug fix: internal API flDOCHAtaReset may cause confusion in the XIP window identification. + * + * Rev 1.66 Feb 15 2007 17:42:06 Einat.Avidan + * add support for DOCH_USE_BURST_MODE_READ_ONLY_IN_DMA + * + * Rev 1.65 Dec 05 2006 14:59:28 Yaniv.Iarovici + * Fix bug in auto secure-wipe mechanism. + * + * Rev 1.64 Dec 03 2006 15:38:56 Yaniv.Iarovici + * Fixed compilation warning + * + * Rev 1.63 Dec 03 2006 13:31:24 Yaniv.Iarovici + * Encapsulate auto wipe-sector operation for Dev1 under '#ifndef DOCH_NO_AUTO_WIPE_SECTORS_DEV1' + * + * Rev 1.62 Nov 30 2006 10:23:36 Yaniv.Iarovici + * 1. Fixed compilation warnings. + * 2. Added SDK level secure-wipe power-failure immunity. + * 3. Fixed flDOCHAtaReset in case of cascaded configuration. + * + * Rev 1.61 Nov 21 2006 14:26:14 Yaniv.Iarovici + * 1. Fixed IRQ handling in case of cascaded configuration. + * 2. Fixed OTW setting of a partition residing on Dev1 (cascaded configuration). + * + * Rev 1.60 Nov 12 2006 09:46:42 Yaniv.Iarovici + * Modify parameter list of doch_reset(). + * + * Rev 1.59 Oct 31 2006 12:23:22 yaniv.iarovici + * Search for the current window after resetting Dev0 in flDOCHAtaReset(). + * + * Rev 1.58 Oct 30 2006 15:50:24 yaniv.iarovici + * Add call to DOCHAddPartition() after creating spanned partition + * for updating actual number of partitions. + * + * Rev 1.57 Oct 25 2006 09:10:26 Yaniv.Iarovici + * Fix for cascaded scenario in which last partition on dev0 is NOT spanned, and is RW protected. + * + * Rev 1.56 Oct 05 2006 11:00:28 yaniv.iarovici + * 1. Retrieve MAX DRQ supported by the device. + * 2. Check that requested DRQ size is supported by the device. + * 3. Remove verify write option from DOCHWriteIPLSingleFloor(). + * + * Rev 1.55 Sep 14 2006 09:56:30 yaniv.iarovici + * DOCHSetCustomParameterSingleFloor() to return DOCH_ProtectionFault in case of protection violation. + * + * Rev 1.54 Sep 13 2006 10:30:46 yaniv.iarovici + * Fix compilation warnings + * + * Rev 1.53 Sep 11 2006 13:45:14 yaniv.iarovici + * Legal header added + * + * Rev 1.52 Sep 10 2006 10:03:14 Yaniv.Iarovici + * 1. Bug Fix: Calculation of total number of partitions in DOCHIdentifyDiskOnChipDevice() in cascaded configuration, when last partition on Dev0 fills the first floor entirely. + * + * 2. Bug Fix: Support creation of Read protected partition which is spanned on both devices in cascaded configuration. + * + * 3. Bug Fix: Setting configuration register values to Dev1 in cascaded configuration (DOCHConfigHW()). + * + * Rev 1.51 Sep 03 2006 14:44:22 Yaniv.Iarovici + * 1. Fixed logic of setting bLastDev0PartSpanned in case last partition on Dev0 fills entire Dev0. (Cascaded configuration) + * 2. Preserve current OTW setting when changing protection type. (Can only be set by AddPartition) + * + * Rev 1.50 Aug 24 2006 11:40:46 Yaniv.Iarovici + * API Change to following protection related routines: + * - DOCHAccessPartWithPwdSingleFloor + * - DOCHDisablePartAccessSingleFloor + * - DOCHSendHostPublicKey + * - DOCHReceiveDochPublicKey + * - DOCHVerifyHostKey + * (The change differs DOCH_ACCESS_ALL_PARTITIONS flag from partition number field + * in ioreq) + * + * Rev 1.49 Aug 22 2006 13:23:36 Yaniv.Iarovici + * 1) Bug fix: 'pdev->bAtaDevNum' was not recovered correctly to 'origDevNum' (multiple places) + * 2) In DOCHWriteIPLSingleFloor(), set rc = DOCH_OK at decleration, to prevent compilation warning + * 3) Bug fix: flDOCHAddPartition - Cascaded configuration + * + * Rev 1.48 Aug 16 2006 08:44:18 Yaniv.Iarovici + * 1) Fix bdCallDOCH() Description + * 2) Check if ETFFS was identified on the device - if not, return 'DOCH_FeatureNotSupported' + * 2) Free MUTEX before returning error when (gDochAccessNanosec == 0) is detected + * 3) Check that Multi-sector transfer mode does not exceed max allowed in DOCHSetDataTransferModeSingleFloor() + * 4) Set pdev->device[devNum].ETFFS_Identified = TRUE adfter a SUCCESSFULL completion of DOCHIdentifyDiskOnChipDeviceSingleFloor() + * 5) Remove unneccesary code from DOCHGetResetStatus() + * 6) Reset pdev->bAtaDevNum to original value upon failure (various places in the code) + * 7) Check that pdev is valid in the various routines + * 8) Change description of DOCHGetPowerMode() and DOCHSetPowerMode() to fit SW Spec 0.84 + * + * Rev 1.47 Aug 09 2006 17:26:50 Polina.Marimont + * initial for DOC Driver 1.0 + * + */ + +#include "flchkdef.h" +#include "flsystyp.h" +#include "flcommon.h" +#include "flsysfun.h" +#include "doch_func.h" +#include "doch_ata.h" +#include "flstdcmp.h" +#include "hib.h" +#include "part_inf.h" +#include "dochtl.h" +#ifdef FL_MIGRATION_VERSION +#include "docsys.h" +#endif /* FL_MIGRATION_VERSION */ + +#ifdef __cplusplus +extern "C" { +#endif + +/******************************************************************************/ +/* + * Global variables + */ +/******************************************************************************/ + +/* NOTE: Global variables with "boolean like" behavior are set to a unique pattern (DOCH_GLOBAL_BOOL_PATTERN) + to indicate them as "TRUE" */ +#ifdef FL_VERIFY_WRITE +FLByte gDochVerifyWrite[DOCH_MAX_SOCKETS]; /*Indicates to perform verify operation on every written sector to the specified socket*/ +#endif /*FL_VERIFY_WRITE*/ + +#ifdef FL_UTILS_QUICK_INIT +FLByte gDochQuickInit = 0; /*For utilities. Makes it possible to seek one dev only*/ +#endif /*FL_UTILS_QUICK_INIT*/ + +FLByte gDochAtaDebug = 0; /*Indicates to retrieve ATA debug buffer upon completion of ATA command */ + +FLByte gSdkInitDone = 0; /*Indicates that DochSDKInit() was completed */ + +FLByte gSdkDOCAddressObtained = 0; /*Indicates that DOC address was obtained (used by DOCHConfigHW) */ + +FLDword gConfigHWDefaults[DOCH_NUM_OF_DCONFIGHW_ITEMS]; +FLByte gConfigHWInitDone = 0; /*Indicates that gConfigHWDefaults[] was set to defaults */ + +FLDword gIPLChunkOffsetInSectors = 0; /*Offset of current IPL chunk to write*/ + +FLByte gSDKUpdatesDiskAttributes = 0; /*Indication that first 0x40 bytes of disk user attributes should be written as well*/ + +FLByte gIsDMAEnabled = 0; /*DMA is Enabled/Disabled*/ + +FLByte gAutoDPDByHost = 0; /*Host enters device to DPD automatically after every command*/ + +FLBoolean gDochIrqEnabled[DOCH_MAX_SOCKETS]; /* holds TRUE, when interrupt enable for socket, FALSE otherwise */ + +extern FLDword gAccessLayerType; + +extern FLByte gATANoTimeout; + +#ifdef DOCH_DMA_CONFIG +extern FLByte gDMAChannelOpen; +#endif /*DOCH_DMA_CONFIG*/ + +extern DOCH_DpdSettings gDpdSettings; + +extern DOCH_Socket sockets [DOCH_MAX_SOCKETS]; + +#ifdef CHECK_POWER_ON_EVERY_COMMAND +extern FLByte gDeviceTurnedOff; +#endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + +extern FLDword gUseShortWaitOnBusy; + +#ifdef DEBUG_TIMEOUT +extern FLDword SysTimerFrequency; +extern void GetInternalSysTimer(FLDword * ticksHigh, FLDword * ticksLow); +#endif /*DEBUG_TIMEOUT*/ + +/******************************************************************************/ +/* + * Extern routines + */ +/******************************************************************************/ + +extern DOCH_Error io_input(DOCH_Socket *pdev, FLSNative devNum, DOCH_Registers* regs, void *buf, FLNative secNum); +extern DOCH_Error io_output(DOCH_Socket *pdev, FLSNative devNum, DOCH_Registers* regs, void *buf, FLNative secNum); +extern DOCH_Error get_out_registers(DOCH_Socket* pdev, FLSNative devNum, DOCH_Registers* out_regs); + +void DOCH_SetBits(FLDword* var, FLDword mask, FLByte offset, FLDword val) +{ + FLDword temp = *var; + + + temp &= ~(mask); + temp |= (val << offset); + + *var = temp; +} + +extern DOCH_Error dochSetMutex(FLByte socketNum, + FLBoolean state, + FLByte partition); + +/******************************************************************************/ +/* + * Static routines + */ +/******************************************************************************/ +static DOCH_Error performSectorsOperation(DOCH_Command cmd, + FLByte devHeadOptions, + DOCH_Socket* pdev, + IOreq* ioreq, + DOCH_Registers* out_regs, + FLSNative sectorsToPerfrom, + FLSNative * sectorNumber, + FLSNative * totalNumOfSectors, + FLSNative * sectorsPerformed, + FLSNative * buf_offset, + FLByte* buf_ptr); + + +#ifdef DOCH_BIG_ENDIAN +static FLWord be_FLWord (FLByte * v); +static FLDword be_FLDword (FLByte * v); +#endif /*DOCH_BIG_ENDIAN*/ + +DOCH_Error DOCHGetParitionUserAttributesSingleFloor(IOreq* ioreq); +DOCH_Error DOCHAccessPartWithPwdSingleFloor(IOreq* ioreq); +DOCH_Error DOCHSetParitionProtectionSingleFloor(IOreq* ioreq); + +/******************************************************************************/ +/* + * Static Buffers + */ +/******************************************************************************/ +static DOCH_PartitionFormatInfo partFormatInfo; +static DOCH_DeviceInfo diskOnChipDeviceInfo; +static DOCH_DeviceInfo diskOnChipDeviceInfo2; +static DOCH_DeviceUserAttr devUserAttr; +static DOCH_PartitionInfo partitionInfoTemp; +static DOCH_PartitionFormatInfoAPI partInfoTemp; +static DOCH_PartitionProtectionAPI protAPI; +static DOCH_PartitionAcessPassword partAccessTemp; +static FLByte currentAttributes[DOCH_SECTOR_SIZE]; +#ifdef FL_VERIFY_WRITE +static FLByte verifyBuf[DOCH_SECTOR_SIZE]; +#endif /*FL_VERIFY_WRITE*/ +static FLDword wipeSectorsDev[((2*DOCH_SECTOR_SIZE) / sizeof(FLDword))]; + +/******************************************************************************/ +/* + * Local MACROs + */ +/******************************************************************************/ +#ifdef DOCH_DMA_CONFIG +#define DOCH_OPEN_DMA_CHANNEL \ + { \ + DMA_Params_S dmaParams; \ + \ + if(pdev->bUseDMA && (gDMAChannelOpen == 0)) \ + { \ + dmaParams.bOpType = DOCH_DMA_OPEN_CHANNEL; \ + DOCH_DMA_CONFIG(&dmaParams); \ + if(dmaParams.fDmaStatus != 0) \ + { \ + DBG_PRINT_ERR_PRM(FLZONE_API,(FLTXT("DOCH_DMA_OPEN_CHANNEL Failed with dmaStatus: %d \r\n"),dmaParams.fDmaStatus)); \ + return DOCH_GeneralFailure; \ + } \ + \ + gDMAChannelOpen = DOCH_GLOBAL_BOOL_PATTERN; \ + \ + DBG_PRINT_FLOW(FLZONE_API, "\r\nDMA Channel opened\r\n"); \ + } \ + } +#endif /*DOCH_DMA_CONFIG*/ + +#define DOCH_SET_ATA_ADDRESS_VALUES(addr_vals, sectorNumber, deviceNum) \ + addr_vals.bSecNum = (FLByte) sectorNumber; \ + addr_vals.bCylLow = (FLByte) (sectorNumber >> 8); \ + addr_vals.bCylHi = (FLByte) (sectorNumber >> 16); \ + addr_vals.bDevHead = (FLByte) (((sectorNumber >> 24) & 0x0f) | DOCH_LBA | (deviceNum<<4)); + + +#define DOCH_PARTITION_ON_DEV0 \ + ((!pdev->sSpanData.secondFloorActive) || (partNum < pdev->sSpanData.bLastPartitionOnDev0) || \ + ((partNum == pdev->sSpanData.bLastPartitionOnDev0) && (!pdev->sSpanData.bLastDev0PartSpanned))) + +#define DOCH_PARTITION_ON_DEV1 \ + (((pdev->sSpanData.secondFloorActive) && (partNum > pdev->sSpanData.bLastPartitionOnDev0)) \ + && (pdev->wNumOfDevices > 1)) + +#define DOCH_PARTITION_IS_SPANNED \ + (((pdev->sSpanData.bLastDev0PartSpanned) && (partNum == pdev->sSpanData.numOfSpannedPartitionOnDev0)) \ + && (pdev->wNumOfDevices > 1)) + +/*----------------------------------------------------------------------*/ +/* p e r f o r m S e c t o r O p e r a t i o n */ +/* */ +/* Performs sector(s) operation */ +/* */ +/* Parameters: */ +/* cmd : ATA command to perform */ +/* pdev : Socket to perform on */ +/* ioreq : IOreq */ +/* totalNumOfSectors : Total num of sectors to perform */ +/* sectorsPerformed : Num of sectors actually performed */ +/* */ +/* Returns: */ +/* device head with proper bit */ +/*----------------------------------------------------------------------*/ +static +DOCH_Error performSectorsOperation(DOCH_Command cmd, + FLByte devHeadOptions, + DOCH_Socket* pdev, + IOreq* ioreq, + DOCH_Registers* out_regs, + FLSNative sectorsToPerfrom, + FLSNative * sectorNumber, + FLSNative * totalNumOfSectors, + FLSNative * sectorsPerformed, + FLSNative * buf_offset, + FLByte* buf_ptr) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + Addressing_Values_s addr_vals; + + /*Perform 1 operation cycle*/ + /*=========================*/ + + /*Set ATA addressing registers*/ + /*---------------------------*/ + DOCH_SET_ATA_ADDRESS_VALUES(addr_vals, (*sectorNumber), (pdev->bAtaDevNum)); + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + if(sectorsToPerfrom < DOCH_MAX_SECTORS) + in_regs.bSectorCount = sectorsToPerfrom; + else + in_regs.bSectorCount = 0; /*DOCH_MAX_SECTORS*/ + + in_regs.bSectorNumber = addr_vals.bSecNum; + in_regs.bCylLow = addr_vals.bCylLow; + in_regs.bCylHigh = addr_vals.bCylHi; + in_regs.bDriveHead = addr_vals.bDevHead | devHeadOptions; + in_regs.bCommandStatus = cmd; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + out_regs, + (void*)(&buf_ptr[*buf_offset]), + sectorsToPerfrom); + + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "performSectorsOperation(): ATA Error: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + DBG_PRINT_ERR(FLZONE_API, "\r\n"); + + return rc; + } + + /*Update feedback values*/ + /*----------------------*/ + *sectorsPerformed += out_regs->bSectorCount; + + /*For next possible cycle*/ + /*-----------------------*/ + *sectorNumber += sectorsToPerfrom; + *totalNumOfSectors -= sectorsToPerfrom; + *buf_offset += sectorsToPerfrom * DOCH_SECTOR_SIZE; + + return DOCH_OK; +} + +#ifdef DOCH_BIG_ENDIAN +/****************************************************************************** + * * + * be _ s h o r t * + * be _ l o n g * + * * + * Little-to-CPU-native integer conversion routines for big-endian CPUs. * + * * + * Parameters : * + * v : correctly aligned little endian value * + * Returns : * + * value in CPU native format * + * * + ******************************************************************************/ + +static +FLWord be_FLWord (FLByte * v) +{ + register FLWord x = *((FLWord *)v); + return ((x >> 8) | (x << 8)); +} + +static +FLDword be_FLDword (FLByte * v) +{ + register FLDword x = *((FLDword *)v); + return ((x >> 24) | ((x >> 8) & 0x0000ff00) | + ((x << 8) & 0x00ff0000) | (x << 24)); +} +#endif /*DOCH_BIG_ENDIAN*/ + +/******************************************************************************/ +/* + * DOCH SDK API Routines + */ +/******************************************************************************/ + +/*----------------------------------------------------------------------*/ +/* b d C a l l D O C H */ +/* */ +/* Performs needed general operations before calling actual function */ +/* Calls appropriate DOCH function */ +/* */ +/* Parameters: */ +/* functionNo : DOCH SDK function to run */ +/* ioreq : DOCH ioreq structure */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error bdCallDOCH(FLSNative functionNo, IOreq FAR2 *ioreq) +{ + DOCH_Error rc; + +#ifdef CHECK_POWER_ON_EVERY_COMMAND + /* gDeviceTurnedOff will be updated by API routines*/ + gDeviceTurnedOff = FALSE; +#endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + + /*If ETFFS wasnt identified, prevent using bdCallDOCH()*/ + if(!sockets[DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)].device[0].ETFFS_Identified) + return DOCH_FeatureNotSupported; + + /* Take mutex for current device */ + rc = dochSetMutex(DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + DOCH_ON, + DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "bdCallDOCH(): dochSetMutex failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + return rc; + } + + /*Check if requested operation is wither Read or Write which are performance critical + (All other operations are directed from within the switch case) + -------------------------------------------------------------*/ + if(functionNo == SDK_READ_PARTITION_SECTORS) + { + rc = DOCHReadPartitionSectors(ioreq); + } + else if (functionNo == SDK_WRITE_PARTITION_SECTORS) + { + rc = DOCHWritePartitionSectors(ioreq); + } + else + { + /*Branch to appropriate DOCH routine according to function#*/ + /*---------------------------------------------------------*/ + switch (functionNo) + { + /*Get Info*/ + case SDK_IDENTIFY_DISKONCHIP_DEVICE: + rc = DOCHIdentifyDiskOnChipDevice(ioreq); + break; + + case SDK_GET_RESET_STATUS: + rc = DOCHGetResetStatus(ioreq); + break; + + case SDK_NOTIFY_RESET: + rc = DOCHNotifyReset(ioreq); + break; + + case SDK_NOTIFY_PLATFORM_RESUMED: + rc = DOCHNotifyPlatformResumed(ioreq); + break; + + case SDK_GET_PARTITION_INFO: + rc = DOCHPartitionInfo(ioreq); + break; + + case SDK_SET_DISK_USER_ATTR: + rc = DOCHSetDiskUserAttributes(ioreq); + break; + + case SDK_GET_DISK_USER_ATTR: + rc = DOCHGetDiskUserAttributes(ioreq); + break; + + case SDK_GET_CONFIG_DATA: + rc = DOCHGetConfigurationData(ioreq); + break; + + case SDK_SET_CONFIG_DATA: + rc = DOCHSetConfigurationData(ioreq); + break; + + /*Media*/ + case SDK_SET_DEFAULT_PARTITION: + rc = DOCHSetDefaultPartition(ioreq); + break; + + case SDK_SET_DATA_XFER_MODE: + rc = DOCHSetDataTransferMode(ioreq); + break; + + case SDK_OPTIMIZE_MEDIA: + rc = DOCHOptimizeMedia(ioreq); + break; + + case SDK_DELETE_PARTITIONS: + rc = DOCHDeletePartitions(ioreq); + break; + + case SDK_ADD_PARTITION: + rc = DOCHAddPartition(ioreq); + break; + + case SDK_UNFORMAT_DEVICE: + rc = DOCHUnformatDevice(ioreq); + break; + + case SDK_WRITE_IPL: + rc = DOCHWriteIPL(ioreq); + break; + + case SDK_READ_IPL: + rc = DOCHReadIPL(ioreq); + break; + + /*IO*/ + case SDK_WRITE_AND_LOCK: + rc = DOCHWriteAndLock(ioreq); + break; + + case SDK_WIPE_SECTORS: + rc = DOCHWipeSectors(ioreq); + break; + + case SDK_FREE_SECTORS: + rc = DOCHFreeSectors(ioreq); + break; + + case SDK_PREPARE_FOR_WRITE: + rc = DOCHPrepareForWrite(ioreq); + break; + +#if 0 + /*Flexi-Flash*/ + case SDK_WRITE_FLEXI_FAST: + rc = DOCHWriteFlexiFast(ioreq); + break; + + case SDK_WRITE_FLEXI_NORMAL: + rc = DOCHWriteFlexiNormal(ioreq); + break; + + case SDK_REWRITE_FLEXI_NORMAL: + rc = DOCHReWriteFlexiNormal(ioreq); + break; +#endif /*0*/ + + /*Protection*/ + case SDK_ACCESS_PART_WITH_PWD: + rc = DOCHAccessPartWithPwd(ioreq); + break; + + case SDK_DISABLE_PART_ACCESS: + rc = DOCHDisablePartAccess(ioreq); + break; + + case SDK_SET_PART_PROTECTION: + rc = DOCHSetParitionProtection(ioreq); + break; + +#if 0 + /*PKI*/ + case SDK_PKI_HOST: + rc = DOCHSendHostPublicKey(ioreq); + break; + + case SDK_PKI_DOCH: + rc = DOCHReceiveDochPublicKey(ioreq); + break; + + case SDK_PKI_VERIFY_HOST_KEY: + rc = DOCHVerifyHostKey(ioreq); + break; +#endif /*0*/ + + /*Custom Parameters*/ + case SDK_GET_CUSTOM_PARAM: + rc = DOCHGetCustomParameter(ioreq); + break; + + case SDK_SET_CUSTOM_PARAM: + rc = DOCHSetCustomParameter(ioreq); + break; + +#if 0 + /*Atomic Read/Write Sequence*/ + case SDK_ATOMIC_WRITE_SEQ: + rc = DOCHManageAtomicWriteSeq(ioreq); + break; + + /*Algorithms*/ + case SDK_REPORT_SUPP_ALG: + rc = DOCHReportSupportedAlgorithms(ioreq); + break; + + case SDK_REPORT_ALG_CAPAB: + rc = DOCHGetAlgorithmCapabilities(ioreq); + break; + + case SDK_SET_ALG_MODE: + rc = DOCHSetAlgorithmMode(ioreq); + break; + + /*Hash*/ + case SDK_AUTO_HASH_CTRL: + rc = DOCHAutoHashControl(ioreq); + break; + + case SDK_READ_CALC_HASH: + rc = DOCHReadCalculatedHash(ioreq); + break; + + case SDK_WRITE_CALC_HASH: + rc = DOCHWriteCalculatedHash(ioreq); + break; + + case SDK_READ_ORIG_HASH: + rc = DOCHReadOriginalHash(ioreq); + break; + + case SDK_WRITE_GIVEN_HASH: + rc = DOCHWriteGivenHash(ioreq); + break; + + case SDK_START_HASH_STREAM_CALC: + rc = DOCHStartHashStreamCalculation(ioreq); + break; + + case SDK_READ_HASH_STREAM_CALC: + rc = DOCHReadStopHashStreamCalc(ioreq); + break; + + case SDK_RETURN_RAND_NUMS: + rc = DOCHReturnRandomNumbers(ioreq); + break; + + case SDK_SET_HASH_KEY: + rc = DOCHSetHashKey(ioreq); + break; + +#endif /*0*/ + + /*General*/ + case SDK_SET_PART_USER_ATTR: + rc = DOCHSetParitionUserAttributes(ioreq); + break; + + case SDK_GET_PART_USER_ATTR: + rc = DOCHGetParitionUserAttributes(ioreq); + break; + + case SDK_SET_POWER_MODE: + rc = DOCHSetPowerMode(ioreq); + break; + + case SDK_GET_POWER_MODE: + rc = DOCHGetPowerMode(ioreq); + break; + + case SDK_HW_CONFIG: + rc = DOCHConfigHW(ioreq); + break; + + case SDK_RECOVER_FROM_POWER_LOSS: + rc = DOCHRecoverFromPowerLoss(ioreq); + break; + + case SDK_CLEAR_ATA_INTERRUPT: + rc = DOCHClearIRQ(ioreq); + break; + + case SDK_GET_PHYSICAL_ADDRESS: + rc = DOCHGetPhysicalAddress(ioreq); + break; + +#ifdef FL_SLPP + case SDK_SLPP_UNLOCK_RANGE: + rc = DOCHSLPPUnlockRange(ioreq); + break; + + case SDK_SLPP_UNLOCK_ENTIRE_PARTITION: + rc = DOCHSLPPUnlockEntirePartition(ioreq); + break; + + case SDK_SLPP_LOCK_RANGE: + rc = DOCHSLPPLockRange(ioreq); + break; + + case SDK_SLPP_STICKY_LOCK_RANGE: + rc = DOCHSLPPStickyLockRange(ioreq); + break; + + case SDK_SLPP_REPORT_LOCKED_RANGES: + rc = DOCHSLPPReportLockedRanges(ioreq); + break; +#endif /*FL_SLPP*/ + + default: + rc = DOCH_FeatureNotSupported; + break; + } + } + +#ifdef DOCH_AUTO_DPD_BY_HOST + if(gAutoDPDByHost == DOCH_GLOBAL_BOOL_PATTERN) + { + FLDword tries; + DOCH_Socket* pdev; + FLDword i; + FLByte status; + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*Protect against access time set to 0*/ + if(gDochAccessNanosec == 0) + { + /* Free mutex for current device */ + dochSetMutex(DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + DOCH_OFF, + DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq)); + + return DOCH_BadParameter; + } + tries = (DOCH_SHORT_WAIT * (1000000UL / gDochAccessNanosec)); + + /*Check if socket is registered*/ + if(pdev != NULL) + { + /*Enter dev0 to DPD mode*/ + /*----------------------*/ + /*Set device*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, DOCH_SELECT_DEV0); + DOCH_DELAY_AFTER_DEVICE_SWITCH(pdev,0); + /*Set device to inactive mode*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_CNT_REG, (DOCH_PM_SET_NONE | DOCH_PM_INACTIVE_MODE)); + + /*Invoke command*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_FEATURES_REG, DOCH_SET_POWER_MODE); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_COMMAND_REG, DOCH_VSCMD_EXT_DEVICE_CTRL); + + /*Wait for Dev0 to become ready*/ + for(i=0; ibRegBase, DOCH_STATUS_REG); + if((status & (DOCH_READY | DOCH_BUSY)) == DOCH_READY) + goto doch_Dev0_DPD_OK; + } + +doch_Dev0_DPD_OK: + + if(pdev->wNumOfDevices > 1) + { + /*Enter dev1 to DPD mode*/ + /*----------------------*/ + /*Set device*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, DOCH_SELECT_DEV1); + DOCH_DELAY_AFTER_DEVICE_SWITCH(pdev,1); + /*Set device to inactive mode*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_CNT_REG, (DOCH_PM_SET_NONE | DOCH_PM_INACTIVE_MODE)); + + /*Invoke command*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_FEATURES_REG, DOCH_SET_POWER_MODE); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_COMMAND_REG, DOCH_VSCMD_EXT_DEVICE_CTRL); + + /*Wait for Dev1 to become ready*/ + for(i=0; ibRegBase, DOCH_STATUS_REG); + if((status & (DOCH_READY | DOCH_BUSY)) == DOCH_READY) + goto doch_Dev1_DPD_OK; + } + +doch_Dev1_DPD_OK: + /*Do Nothing*/; + } + } + } +#endif /*DOCH_AUTO_DPD_BY_HOST*/ + + /* Free mutex for current device */ + dochSetMutex(DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + DOCH_OFF, + DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq)); + + +#ifdef CHECK_POWER_ON_EVERY_COMMAND + /*In case Power Fail was detected, return DOCH_DeviceTurnedOff*/ + if( gDeviceTurnedOff==DOCH_GLOBAL_BOOL_PATTERN ) + { + return DOCH_DeviceTurnedOff; + } +#endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + + return rc; +} + +/*----------------------------------------------------------------------*/ +/* D O C H S e t D e f a u l t P a r t i t i o n */ +/* */ +/* Set default partition for Standard-ATA commands */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irCount : SET_DEFAULT_PARTITION_TEMP */ +/* SET_DEFAULT_PARTITION_PERM */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_SET_DEFAULT_PARTITION */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHSetDefaultPartition(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + FLByte dev_head_opt; + DOCH_Socket* pdev; + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check if Partition exceeds number of existing partitions*/ + /*--------------------------------------------------------*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + if(ioreq->irCount == SET_DEFAULT_PARTITION_PERM) + dev_head_opt = PERM_DEFAULT_PART_OP; + else + dev_head_opt = 0; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_SET_DEFAULT_PARTITION; + in_regs.bSectorCount = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = (DOCH_SELECT_DEV(pdev->bAtaDevNum) | (dev_head_opt)); + in_regs.bCommandStatus = DOCH_VSCMD_PARTITION_MANAGEMENT; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHSetDefaultPartition(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* D O C H S e t D a t a T r a n s f e r M o d e */ +/* */ +/* Set Data transfer mode */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : Requested data transfer mode: */ +/* DOCH_DATA_XFER_MODE_SINGLE */ +/* DOCH_DATA_XFER_MODE_MULT */ +/* irLength : In case of DOCH_DATA_XFER_MODE_MULT, */ +/* specifies DRQ block size */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_SET_DATA_XFER_MODE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHSetDataTransferModeSingleFloor(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_TransferMode requstedXferMode = (DOCH_TransferMode)(ioreq->irCount); + FLByte requestedDrqSize = (FLByte)(ioreq->irLength); + FLSNative socketNum = DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq); + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, socketNum); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check that Multi-sector transfer mode does not exceed max allowed*/ + if((ioreq->irCount == DOCH_DATA_XFER_MODE_MULT) && + ((ioreq->irLength > DOCH_MAX_DRQ_SUPPORTED) || + (ioreq->irLength > (FLSDword)pdev->device[pdev->bAtaDevNum].dwMulti_MAX)) + ) + return DOCH_FeatureNotSupported; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_SET_DATA_XFER_MODE; + in_regs.bSectorCount = (FLByte)(ioreq->irCount); + if(ioreq->irCount == DOCH_DATA_XFER_MODE_MULT) + in_regs.bSectorNumber = (FLByte)(ioreq->irLength); + else + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead =DOCH_SELECT_DEV(pdev->bAtaDevNum); + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( socketNum, + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + if(rc == DOCH_OK) + { + /*If operation succeeded - update transfer mode in SDK as well*/ + /*------------------------------------------------------------*/ + rc = doch_setTransferMode(socketNum, pdev->bAtaDevNum, requstedXferMode, requestedDrqSize); + + return rc; + } + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHSetDataTransferModeSingleFloor(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d\r\n"), rc, pdev->bAtaDevNum)); + return DOCH_GeneralFailure; + } + +} + +DOCH_Error DOCHSetDataTransferMode(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + DOCH_Socket* pdev; + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + pdev->bAtaDevNum = 0; + rc = DOCHSetDataTransferModeSingleFloor(ioreq); + if(rc != DOCH_OK) + return rc; + + if(pdev->wNumOfDevices > 1) + { + pdev->bAtaDevNum = 1; + rc = DOCHSetDataTransferModeSingleFloor(ioreq); + pdev->bAtaDevNum = 0; + } + + return rc; +} + +/*----------------------------------------------------------------------*/ +/* D O C H I d e n t i f y D i s k O n C h i p D e v i c e */ +/* */ +/* Returns general information about the Device */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : DOCH_IDENTIFY_FROM_FLASH */ +/* DOCH_IDENTIFY_EXISTANCE */ +/* irData : Address of DOCH_DeviceInfo struct */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_IDENTIFY_DISKONCHIP_DEVICE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHIdentifyDiskOnChipDeviceSingleFloor(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Socket* pdev; + DOCH_DeviceInfo* localDiskOnChipDeviceInfo = (DOCH_DeviceInfo*)(ioreq->irData); + FLSNative devNum; + + DOCH_Registers in_regs; + DOCH_Registers out_regs; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + devNum = pdev->bAtaDevNum; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_IDENTIFY_DISKONCHIP_DEVICE; + in_regs.bSectorCount = 0; + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = (DOCH_SELECT_DEV(pdev->bAtaDevNum) | ((FLByte)ioreq->irCount)); + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + devNum, + &in_regs, + &out_regs, + ioreq->irData, + sizeof(DOCH_DeviceInfo) / DOCH_SECTOR_SIZE); + + + #ifdef DOCH_BIG_ENDIAN + /*In case of a BIG ENDIAN host CPU, reorder bytes in 16 and 32 Bit variables*/ + localDiskOnChipDeviceInfo->wVersion = be_FLWord((FLByte*)&localDiskOnChipDeviceInfo->wVersion); + + localDiskOnChipDeviceInfo->dwCommandFlagsOrStatuses = be_FLDword((FLByte*)&localDiskOnChipDeviceInfo->dwCommandFlagsOrStatuses); + localDiskOnChipDeviceInfo->dwDiskAttributes1 = be_FLDword((FLByte*)&localDiskOnChipDeviceInfo->dwDiskAttributes1); + localDiskOnChipDeviceInfo->dwRservedGateKeeperAttr = be_FLDword((FLByte*)&localDiskOnChipDeviceInfo->dwRservedGateKeeperAttr); + + localDiskOnChipDeviceInfo->wTotalNumOfPartitions = be_FLWord((FLByte*)&localDiskOnChipDeviceInfo->wTotalNumOfPartitions); + localDiskOnChipDeviceInfo->wDefaultPartitionNumber = be_FLWord((FLByte*)&localDiskOnChipDeviceInfo->wDefaultPartitionNumber); + + localDiskOnChipDeviceInfo->dwUnformattedCapacity = be_FLDword((FLByte*)&localDiskOnChipDeviceInfo->dwUnformattedCapacity); + + localDiskOnChipDeviceInfo->dwReservedConfigPartitionSize = be_FLDword((FLByte*)&localDiskOnChipDeviceInfo->dwReservedConfigPartitionSize); + localDiskOnChipDeviceInfo->dwUnitSize = be_FLDword((FLByte*)&localDiskOnChipDeviceInfo->dwUnitSize); + localDiskOnChipDeviceInfo->dwConfigurationPartitionExistsSign = be_FLDword((FLByte*)&localDiskOnChipDeviceInfo->dwConfigurationPartitionExistsSign); + #endif /*DOCH_BIG_ENDIAN*/ + + /*Update device structure*/ + /*=======================*/ + if(rc == DOCH_OK) + { + /*ETFFS detected*/ + pdev->device[devNum].ETFFS_Identified = TRUE; + + /*Extract MAX DRQ size from the Disk Attributes field*/ + pdev->device[devNum].dwMulti_MAX = (1 << + ((localDiskOnChipDeviceInfo->dwDiskAttributes1 & DOCH_DA1B_MAX_MULTI_SEC_XFER_SIZE) >> DOCH_DA1O_MAX_MULTI_SEC_XFER_SIZE)); + + if((localDiskOnChipDeviceInfo->dwUnformattedCapacity != 0) && + (localDiskOnChipDeviceInfo->wVersionCompatability == 0) +#ifndef DOCH_DONT_CHECK_EXISTANCE_SIGN + && (localDiskOnChipDeviceInfo->dwConfigurationPartitionExistsSign == DOCH_CONFIGURATION_EXISTS_SIGN) +#endif /*DOCH_DONT_CHECK_EXISTANCE_SIGN*/ + ) + { + rc = update_device_info(pdev, localDiskOnChipDeviceInfo, devNum); + + #ifdef CHECK_POWER_ON_EVERY_COMMAND + { + IOreq ioreq2; + + /*Make sure next calls to DOCHGetResetStatus() will reflect actual reset*/ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irHandle = ioreq->irHandle; + DOCHGetResetStatus(&ioreq2); + } + #endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + + return DOCH_OK; + } + DBG_PRINT_ERR(FLZONE_API, "ERROR: DOCHIdentifyDiskOnChipDevice(): read incorrect data\r\n"); + } + if(devNum == 0) + { + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "ERROR: DOCHIdentifyDiskOnChipDevice(): failed "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("with status: 0x%x \r\n"), rc)); + } + } + else + { + /*Prevent invoking Dev1 if it was not detected!!!*/ + tffsset(&pdev->sSpanData, 0, sizeof(pdev->sSpanData)); + + DBG_PRINT_WRN(FLZONE_API, "DOCHIdentifyDiskOnChipDevice(): Dev1 not found\r\n"); + } + return DOCH_GeneralFailure; +} + +DOCH_Error DOCHIdentifyDiskOnChipDevice(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq ioreq2; + DOCH_Socket* pdev; + DOCH_DeviceInfo* tempDiskOnChipDeviceInfo; + FLByte requestedDevice; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + requestedDevice = pdev->bAtaDevNum; + + /*Identify Dev0*/ + tempDiskOnChipDeviceInfo = (DOCH_DeviceInfo*)(ioreq->irData); + pdev->bAtaDevNum = 0; + + /*Identify command should have a short timeout*/ + gUseShortWaitOnBusy = DOCH_LONG_IDENTIFY_TIMEOUT; + rc = DOCHIdentifyDiskOnChipDeviceSingleFloor(ioreq); + gUseShortWaitOnBusy = 0; + + pdev->bAtaDevNum = requestedDevice; + if(rc != DOCH_OK) + return rc; + + /*If only 1 device is present, return*/ + if(pdev->wNumOfDevices > 1) + { + /*Identify Dev1*/ + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + ioreq2.irData = &diskOnChipDeviceInfo2; + + pdev->bAtaDevNum = 1; + /*Identify command should have a short timeout*/ + gUseShortWaitOnBusy = DOCH_LONG_IDENTIFY_TIMEOUT; + rc = DOCHIdentifyDiskOnChipDeviceSingleFloor(&ioreq2); + gUseShortWaitOnBusy = 0; + pdev->bAtaDevNum = requestedDevice; + if(rc != DOCH_OK) + return rc; + + /*Combine data*/ + tempDiskOnChipDeviceInfo->dwUnformattedCapacity += diskOnChipDeviceInfo2.dwUnformattedCapacity; + + tempDiskOnChipDeviceInfo->wTotalNumOfPartitions += diskOnChipDeviceInfo2.wTotalNumOfPartitions; + + if(diskOnChipDeviceInfo2.wTotalNumOfPartitions > 1) + { + if((pdev->sSpanData.bLastDev0PartSpanned)) + tempDiskOnChipDeviceInfo->wTotalNumOfPartitions -= 2; + else + tempDiskOnChipDeviceInfo->wTotalNumOfPartitions -= 1; + } + else if(diskOnChipDeviceInfo2.wTotalNumOfPartitions == 1) + tempDiskOnChipDeviceInfo->wTotalNumOfPartitions -= 1; + } + + return DOCH_OK; +} + +/*----------------------------------------------------------------------*/ +/* D O C H G e t R e s e t S t a t u s */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_GET_RESET_STATUS */ +/* */ +/* Returns: */ +/* irCount : 0 = No reset since last query */ +/* 1 = The device has been reset since last*/ +/* query */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHGetResetStatus(IOreq* ioreq) +{ + DOCH_Error rc; + + DOCH_Registers in_regs; + DOCH_Registers out_regs; + + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + pdev->bUseInterrupt=FALSE; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_GET_RESET_STATUS; + in_regs.bSectorCount = 0; + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead =DOCH_SELECT_DEV (pdev->bAtaDevNum); + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + /*Update device structure*/ + /*=======================*/ + if(rc == DOCH_OK) + { + /*Return reset status*/ + ioreq->irCount = out_regs.bSectorCount; + + return DOCH_OK; + } + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHGetResetStatus(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* D O C H N o t i f y R e s e t */ +/* */ +/* Notify the Device on an upcoming reset initiated by the Host. */ +/* Host should NOT perform actual reset before this command completes */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_NOTIFY_RESET */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHNotifyResetSingleFloor(IOreq* ioreq) +{ + DOCH_Error rc; + + DOCH_Registers in_regs; + DOCH_Registers out_regs; + + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_NOTIFY_RESET; + in_regs.bSectorCount = 0; + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_SELECT_DEV(pdev->bAtaDevNum); + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + 0, + &in_regs, + &out_regs, + NULL, + 0); + + /*Update device structure*/ + /*=======================*/ + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHNotifyResetSingleFloor(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d\r\n"), rc, pdev->bAtaDevNum)); + + return DOCH_GeneralFailure; + } + + return DOCH_OK; +} + +DOCH_Error DOCHNotifyReset(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + DOCH_Socket* pdev; + FLByte origDevNum; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + origDevNum = pdev->bAtaDevNum; + + pdev->bAtaDevNum = 0; + rc = DOCHNotifyResetSingleFloor(ioreq); + if(rc != DOCH_OK) + { + pdev->bAtaDevNum = origDevNum; + return rc; + } + + if(pdev->wNumOfDevices > 1) + { + pdev->bAtaDevNum = 1; + rc = DOCHNotifyResetSingleFloor(ioreq); + pdev->bAtaDevNum = origDevNum; + } + + return rc; +} + +/*----------------------------------------------------------------------*/ +/* D O C H N o t i f y P l a t f o r m R e s u m e d */ +/* */ +/* Notify the Device that there was a reset, */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_NOTIFY_PLATFORM_RESUMED */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHNotifyPlatformResumedSingleFloor(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq ioreq2; + + DOCH_Registers in_regs; + DOCH_Registers out_regs; + + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_NOTIFY_PLATFORM_RESUMED; + in_regs.bSectorCount = 0; + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_SELECT_DEV(pdev->bAtaDevNum); + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + 0, + &in_regs, + &out_regs, + NULL, + 0); + + /*Update device structure*/ + /*=======================*/ + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHNotifyPlatformResumedSingleFloor(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d\r\n"), rc,pdev->bAtaDevNum)); + + return DOCH_GeneralFailure; + } + + /*Restore DPD settings */ + /*=====================*/ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + + ioreq2.irFlags = (DOCH_PM_SET_BOTH_MODES | DOCH_PM_WORK_MODE); + ioreq2.irCount = (gDpdSettings.activeMode | gDpdSettings.inActiveMode); + ioreq2.irLength = gDpdSettings.timeOut; + + rc = DOCHSetPowerMode(&ioreq2); + if(rc != DOCH_OK) + return rc; + + /*Restore transfer mode */ + /*======================*/ + tffsset(&ioreq2, 0, sizeof(ioreq)); + + ioreq2.irCount = pdev->device[pdev->bAtaDevNum].dataTransferMode; + ioreq2.irLength = pdev->device[pdev->bAtaDevNum].dwMulti_Current; + + rc = DOCHSetDataTransferModeSingleFloor(&ioreq2); + if(rc != DOCH_OK) + return rc; + + + return DOCH_OK; +} + +DOCH_Error DOCHNotifyPlatformResumed(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + DOCH_Socket* pdev; + FLByte origDevNum; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + origDevNum = pdev->bAtaDevNum; + + pdev->bAtaDevNum = 0; + rc = DOCHNotifyPlatformResumedSingleFloor(ioreq); + if(rc != DOCH_OK) + { + pdev->bAtaDevNum = origDevNum; + return rc; + } + + if(pdev->wNumOfDevices > 1) + { + pdev->bAtaDevNum = 1; + rc = DOCHNotifyPlatformResumedSingleFloor(ioreq); + pdev->bAtaDevNum = origDevNum; + } + + return rc; +} + +/*----------------------------------------------------------------------*/ +/* f l D O C H S e t D i s k U s e r A t t r i b u t e s */ +/* */ +/* Set disk user attributes . */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irData : Pointer to 1 sector of data */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_SET_DISK_USER_ATTR */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHSetDiskUserAttributes(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq ioreq2; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + +#ifdef DOCH_BIG_ENDIAN + DOCH_DeviceUserAttr* devUserAttrOrig = (DOCH_DeviceUserAttr*)(ioreq->irData); + DOCH_PartitionSpanData* devSpanInfo= &devUserAttrOrig->sdkAttributes.sSpanInfo; + DOCH_SecureDeleteDev1* devSecureDelete= &devUserAttrOrig->sdkAttributes.sSecureDeleteDev1; +#endif /*DOCH_BIG_ENDIAN*/ + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + if(!gSDKUpdatesDiskAttributes) + { + /*First retrieve current attributes sector + (for protecting first 0x40 bytes that are SDK specific*/ + /*------------------------------------------------------*/ + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + ioreq2.irData = currentAttributes; + DOCHGetDiskUserAttributes(&ioreq2); + + /*Use currentAttributes bytes 0x41..0x200 to set requested*/ + /*--------------------------------------------------------*/ + tffscpy(ioreq->irData, currentAttributes, DOCH_PART_INFO_SDK_RESERVED_BYTES); + } + +#ifdef DOCH_BIG_ENDIAN + /*In case of a BIG ENDIAN host CPU, reorder bytes in 16 and 32 Bit variables*/ + devSpanInfo->dwSpanSector = be_FLDword((FLByte*)&devSpanInfo->dwSpanSector); + devSpanInfo->dwSpanSizeOnDev0 = be_FLDword((FLByte*)&devSpanInfo->dwSpanSizeOnDev0); + devSecureDelete->dwSecureDeleteNumOfSectors = be_FLDword ((FLByte*)&devSecureDelete->dwSecureDeleteNumOfSectors); + devSecureDelete->dwSecureDeleteStartSector = be_FLDword ((FLByte*)&devSecureDelete->dwSecureDeleteStartSector); +#endif /*DOCH_BIG_ENDIAN*/ + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_SET_DISK_USER_ATTR; + in_regs.bSectorCount = 0; + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = (DOCH_SELECT_DEV(pdev->bAtaDevNum)); + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + ioreq->irData, + (1)); + +#ifdef DOCH_BIG_ENDIAN + /*The spanInfo buffer is in use later on, therefore recover it*/ + devSpanInfo->dwSpanSector = be_FLDword((FLByte*)&devSpanInfo->dwSpanSector); + devSpanInfo->dwSpanSizeOnDev0 = be_FLDword((FLByte*)&devSpanInfo->dwSpanSizeOnDev0); + devSecureDelete->dwSecureDeleteNumOfSectors = be_FLDword ((FLByte*)&devSecureDelete->dwSecureDeleteNumOfSectors); + devSecureDelete->dwSecureDeleteStartSector = be_FLDword ((FLByte*)&devSecureDelete->dwSecureDeleteStartSector); +#endif /*DOCH_BIG_ENDIAN*/ + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHSetDiskUserAttributes(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* f l D O C H G e t D i s k U s e r A t t r i b u t e s */ +/* */ +/* Get disk user attributes . */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irData : Pointer to 1 sector of data */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_GET_DISK_USER_ATTR */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHGetDiskUserAttributes(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + +#ifdef DOCH_BIG_ENDIAN + DOCH_DeviceUserAttr* devUserAttrOrig = (DOCH_DeviceUserAttr*)(ioreq->irData); + DOCH_PartitionSpanData* devSpanInfo= &devUserAttrOrig->sdkAttributes.sSpanInfo; + DOCH_SecureDeleteDev1* devSecureDelete= &devUserAttrOrig->sdkAttributes.sSecureDeleteDev1; +#endif /*DOCH_BIG_ENDIAN*/ + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_GET_DISK_USER_ATTR; + in_regs.bSectorCount = 0; + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = (DOCH_SELECT_DEV(pdev->bAtaDevNum)); + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + ioreq->irData, + (1)); + + +#ifdef DOCH_BIG_ENDIAN + /*In case of a BIG ENDIAN host CPU, reorder bytes in 16 and 32 Bit variables*/ + devSpanInfo->dwSpanSector = be_FLDword((FLByte*)&devSpanInfo->dwSpanSector); + devSpanInfo->dwSpanSizeOnDev0 = be_FLDword((FLByte*)&devSpanInfo->dwSpanSizeOnDev0); + devSecureDelete->dwSecureDeleteNumOfSectors = be_FLDword ((FLByte*)&devSecureDelete->dwSecureDeleteNumOfSectors); + devSecureDelete->dwSecureDeleteStartSector = be_FLDword ((FLByte*)&devSecureDelete->dwSecureDeleteStartSector); +#endif /*DOCH_BIG_ENDIAN*/ + + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHGetDiskUserAttributes(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* f l D O C H G e t C o n f i g u r a t i o n D a t a */ +/* */ +/* Read the device configuration data. No authentication is required */ +/* for calling this command, but the fields containing keys in the */ +/* configuration data will be masked by ETFFS using zeros. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irData : Pointer to 1..3 sector(s) of data. */ +/* irCount : Sector offset in the configuration data to start */ +/* reading from. */ +/* irLength : Number of sectors of configuration data to read. */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_GET_CONFIGURATION_DATA */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHGetConfigurationData(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_GET_CONFIGURATION_DATA; + in_regs.bSectorCount = (FLByte)ioreq->irLength; + in_regs.bSectorNumber = (FLByte)ioreq->irCount; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = (DOCH_SELECT_DEV(pdev->bAtaDevNum)); + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + ioreq->irData, + (ioreq->irLength)); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHGetConfigurationData(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* f l D O C H S e t C o n f i g u r a t i o n D a t a */ +/* */ +/* Save the device configuration data. Calling this command will */ +/* succeed only if there are no partitions present on the media */ +/* (including partition 0). */ +/* You should use this command in the process of duplicating DiskOnChip */ +/* device to make sure all configuration data of the original device */ +/* have been duplicated to the new device. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irData : Pointer to 1..3 sector(s) of data. */ +/* irCount : Sector offset in the configuration data to start */ +/* writing from. */ +/* irLength : Number of sectors of configuration data to write.*/ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_SET_CONFIGURATION_DATA */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHSetConfigurationData(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_SET_CONFIGURATION_DATA; + in_regs.bSectorCount = (FLByte)ioreq->irLength; + in_regs.bSectorNumber = (FLByte)ioreq->irCount; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = (DOCH_SELECT_DEV(pdev->bAtaDevNum)); + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + ioreq->irData, + (ioreq->irLength)); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHSetConfigurationData(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* D O C H P a r t i t i o n I n f o */ +/* */ +/* Get information about a specific partition. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Address of user buffer to read partition */ +/* information into. */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_GET_PARTITION_INFO */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHPartitionInfoSingleFloor(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Socket * pdev; + +#ifdef DOCH_BIG_ENDIAN + DOCH_PartitionInfo* partInfo = (DOCH_PartitionInfo*)(ioreq->irData); + DOCH_PartitionInfo* partInfoToBig = partInfo; +#endif /*DOCH_BIG_ENDIAN*/ + + DOCH_Registers in_regs; + DOCH_Registers out_regs; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check if Partition exceeds number of existing partitions*/ + /*--------------------------------------------------------*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_GET_PARTITION_INFO; + in_regs.bSectorCount = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_SELECT_DEV(pdev->bAtaDevNum); + in_regs.bCommandStatus = DOCH_VSCMD_PARTITION_MANAGEMENT; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + ioreq->irData, + (sizeof(DOCH_PartitionInfo) / DOCH_SECTOR_SIZE)); + +#ifdef DOCH_BIG_ENDIAN + /*In case of a BIG ENDIAN host CPU, reorder bytes in 16 and 32 Bit variables*/ + partInfoToBig->dwCommandFlagsOrStatuses = be_FLDword((FLByte*)&partInfoToBig->dwCommandFlagsOrStatuses); + partInfoToBig->partitionAttributes1 = be_FLDword((FLByte*)&partInfoToBig->partitionAttributes1); + partInfoToBig->partitionAttributes2 = be_FLDword((FLByte*)&partInfoToBig->partitionAttributes2); + partInfoToBig->nPartitionSize = be_FLDword((FLByte*)&partInfoToBig->nPartitionSize); + partInfoToBig->nFastAreaSize = be_FLDword((FLByte*)&partInfoToBig->nFastAreaSize); + + partInfoToBig->wFastAreaFactor = be_FLWord((FLByte*)&partInfoToBig->wFastAreaFactor); + + partInfoToBig->wPartitionStartSector = be_FLWord((FLByte*)&partInfoToBig->wPartitionStartSector); + partInfoToBig->wCurrentSectorsPerTrack = be_FLWord((FLByte*)&partInfoToBig->wCurrentSectorsPerTrack); + partInfoToBig->wDefaultSectorsPerTrack = be_FLWord((FLByte*)&partInfoToBig->wDefaultSectorsPerTrack); + partInfoToBig->wCurrentCylinders = be_FLWord((FLByte*)&partInfoToBig->wCurrentCylinders); + partInfoToBig->wDefaultCylinders = be_FLWord((FLByte*)&partInfoToBig->wDefaultCylinders); + partInfoToBig->wCurrentHeads = be_FLWord((FLByte*)&partInfoToBig->wCurrentHeads); + partInfoToBig->wDefaultHeads = be_FLWord((FLByte*)&partInfoToBig->wDefaultHeads); + + partInfoToBig->wFastAreaSectorsInErasableUnit = be_FLWord((FLByte*)&partInfoToBig->wFastAreaSectorsInErasableUnit); + partInfoToBig->wNormalAreaSectorsInErasableUnit = be_FLWord((FLByte*)&partInfoToBig->wNormalAreaSectorsInErasableUnit); + partInfoToBig->wRecommendedSectorsPerCluster = be_FLWord((FLByte*)&partInfoToBig->wRecommendedSectorsPerCluster); + partInfoToBig->wFastMaxRelatedSectors = be_FLWord((FLByte*)&partInfoToBig->wFastMaxRelatedSectors); + partInfoToBig->wNormalMaxRelatedSectors = be_FLWord((FLByte*)&partInfoToBig->wNormalMaxRelatedSectors); +#endif /*DOCH_BIG_ENDIAN*/ + + /*Update pdev fields*/ +#if 0 + pdev->device[pdev->bAtaDevNum].dwMulti_Current = + ((partInfo->dwCommandFlagsOrStatuses & DOCH_DCFSB_CURRENT_MULTI_SECTOR) >> DOCH_DCFSO_CURRENT_MULTI_SECTOR); +#endif /* 0 */ + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHPartitionInfoSingleFloor(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d \r\n"), rc, pdev->bAtaDevNum)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else + return DOCH_GeneralFailure; + } +} + +DOCH_Error DOCHPartitionInfo(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq ioreq2; + DOCH_Socket* pdev; + DOCH_PartitionInfo* partInfo; + FLByte partNum = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + FLByte origDevNum; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + origDevNum = pdev->bAtaDevNum; + + /*If partition resides ENTIRELY on Dev0*/ + /*=====================================*/ + if(DOCH_PARTITION_ON_DEV0) + { + pdev->bAtaDevNum = 0; + rc = DOCHPartitionInfoSingleFloor(ioreq); + pdev->bAtaDevNum = origDevNum; + return rc; + } + + /*If partition resides ENTIRELY on Dev1 - return info*/ + /*===================================================*/ + if(DOCH_PARTITION_ON_DEV1) + { + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + + if(pdev->sSpanData.bLastDev0PartSpanned) + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0 + 1)); + else + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0)); + + pdev->bAtaDevNum = 1; + rc = DOCHPartitionInfoSingleFloor(&ioreq2); + pdev->bAtaDevNum = origDevNum; + return rc; + } + + /*If partition is spanned - collect both infos and combine*/ + /*========================================================*/ + if(DOCH_PARTITION_IS_SPANNED) + { + /*Retrieve first chunk info*/ + /*-------------------------*/ + pdev->bAtaDevNum = 0; + partInfo = (DOCH_PartitionInfo*)(ioreq->irData); + rc = DOCHPartitionInfoSingleFloor(ioreq); + if(rc != DOCH_OK) + return rc; + + /*Retrieve 2nd chunk info*/ + /*-----------------------*/ + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + ioreq2.irData = &partitionInfoTemp; + + if(pdev->sSpanData.bLastDev0PartSpanned) + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0 + 1)); + else + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0)); + + pdev->bAtaDevNum = 1; + rc = DOCHPartitionInfoSingleFloor(&ioreq2); + pdev->bAtaDevNum = origDevNum; + if(rc != DOCH_OK) + return rc; + + /*Combine info*/ + /*------------*/ + partInfo->nPartitionSize += partitionInfoTemp.nPartitionSize; + partInfo->nFastAreaSize += partitionInfoTemp.nFastAreaSize; + } + + return DOCH_OK; +} + + +/*----------------------------------------------------------------------*/ +/* D O C H D e l e t e P a r t i t i o n s */ +/* */ +/* Delete range of partitions */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irFlags : DOCH_NORMAL_OPERATION */ +/* DOCH_IMMEDIATE_OPERATION */ +/* DOCH_FAST_PARTITOIN_DELETE */ +/* DOCH_COMPLETE_PARTITION_DELETE */ +/* irCount : First partition to delete */ +/* irLength : Last partition to delete */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_DELETE_PARTITIONS */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHDeletePartitionsSingleFloor(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq ioreq2; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + FLByte action_type = 0; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + if((ioreq->irFlags & DOCH_IMMEDIATE_OPERATION) == DOCH_IMMEDIATE_OPERATION) + action_type |= ERASE_IMMEDIATE; + + if((ioreq->irFlags & DOCH_COMPLETE_PARTITION_DELETE) == DOCH_COMPLETE_PARTITION_DELETE) + action_type |= DELETE_PARTITIONS_COMPLETE; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_DELETE_PARTITIONS; + in_regs.bSectorCount = (FLByte)(ioreq->irCount); + in_regs.bSectorNumber = (FLByte)(ioreq->irLength); + in_regs.bCylLow = 0; + in_regs.bCylHigh = 'D'; + in_regs.bDriveHead = (DOCH_SELECT_DEV(pdev->bAtaDevNum) | action_type); + in_regs.bCommandStatus = DOCH_VSCMD_PARTITION_MANAGEMENT; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + if(rc == DOCH_OK) + { + pdev->wTotalNumOfPartitions = 0; + tffsset(&ioreq2, 0, sizeof(ioreq2)); + DOCH_SET_SOCKET_TO_IOREQ_HANDLE(&ioreq2, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + ioreq2.irData = &diskOnChipDeviceInfo; + rc = DOCHIdentifyDiskOnChipDevice(&ioreq2); + if(rc != DOCH_OK) + return rc; + + pdev->wTotalNumOfPartitions = diskOnChipDeviceInfo.wTotalNumOfPartitions; + + return DOCH_OK; + } + else + { + + DBG_PRINT_ERR(FLZONE_API, "DOCHDeletePartitionsSingleFloor(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d\r\n"), rc, pdev->bAtaDevNum)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else + return DOCH_GeneralFailure; + } +} + +DOCH_Error DOCHDeletePartitions(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq ioreq2; + DOCH_Socket* pdev; + FLByte origDevNum; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + origDevNum = pdev->bAtaDevNum; + + /*If partition resides ENTIRELY on Dev0 - return info*/ + /*===================================================*/ + if(!pdev->sSpanData.secondFloorActive || pdev->wNumOfDevices ==1) + { + pdev->bAtaDevNum = 0; + rc = DOCHDeletePartitionsSingleFloor(ioreq); + pdev->bAtaDevNum = origDevNum; + return rc; + } + else + { + /*Protect against illegal operation*/ + if(ioreq->irLength < (pdev->wTotalNumOfPartitions-1)) + { + pdev->bAtaDevNum = origDevNum; + return DOCH_GeneralFailure; + } + + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + + /*Do not delete partitions from Dev0 if they do not reside on it!*/ + if(ioreq->irCount <= pdev->sSpanData.bLastPartitionOnDev0) + { + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + + /*If last partition to delete resides on Dev1, erase irCount and on on Dev0 as well*/ + if(ioreq->irLength >= pdev->sSpanData.bLastPartitionOnDev0) + ioreq2.irLength = 0xFF; + + pdev->bAtaDevNum = 0; + rc = DOCHDeletePartitionsSingleFloor(&ioreq2); + if(rc != DOCH_OK) + { + pdev->bAtaDevNum = origDevNum; + return rc; + } + + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + + /*Preserve IPL on Dev1 if it was preserved on Dev0*/ + if(ioreq->irCount == 0) + ioreq2.irCount = 0; + else + ioreq2.irCount = 1; + + ioreq2.irLength = 0xFF; + + pdev->bAtaDevNum = 1; + rc = DOCHDeletePartitionsSingleFloor(&ioreq2); + pdev->bAtaDevNum = origDevNum; + + if(rc != DOCH_OK) + { + pdev->bAtaDevNum = origDevNum; + return rc; + } + } + else + { + ioreq2.irCount = ((ioreq->irCount - pdev->sSpanData.bLastPartitionOnDev0) + 1); + if(ioreq->irLength != 0xFF) + ioreq2.irLength = ((ioreq->irLength - pdev->sSpanData.bLastPartitionOnDev0) + 1); + + pdev->bAtaDevNum = 1; + rc = DOCHDeletePartitionsSingleFloor(&ioreq2); + pdev->bAtaDevNum = origDevNum; + + if(rc != DOCH_OK) + return rc; + + /*Still spanned!*/ + return DOCH_OK; + } + } + + /*Update span info structure*/ + /*--------------------------*/ + pdev->bAtaDevNum = 0; + + /*Retrieve current attributes*/ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irData = &devUserAttr; + rc = DOCHGetDiskUserAttributes(&ioreq2); + if(rc != DOCH_OK) + { + pdev->bAtaDevNum = origDevNum; + return rc; + } + + /*Set span info*/ + devUserAttr.sdkAttributes.sSpanInfo.bLastDev0PartSpanned = FALSE; + devUserAttr.sdkAttributes.sSpanInfo.secondFloorActive = FALSE; + devUserAttr.sdkAttributes.sSpanInfo.dwSpanSector = 0; + devUserAttr.sdkAttributes.sSpanInfo.bLastPartitionOnDev0 = + devUserAttr.sdkAttributes.sSpanInfo.numOfSpannedPartitionOnDev0 = 0; + + /*Set attributes back to the device*/ + gSDKUpdatesDiskAttributes = DOCH_GLOBAL_BOOL_PATTERN; + rc = DOCHSetDiskUserAttributes(&ioreq2); + gSDKUpdatesDiskAttributes = 0; + if(rc != DOCH_OK) + { + pdev->bAtaDevNum = origDevNum; + return rc; + } + + /*Update pdev as well*/ + tffscpy(&pdev->sSpanData, &devUserAttr.sdkAttributes.sSpanInfo, sizeof(pdev->sSpanData)); + + pdev->bAtaDevNum = origDevNum; + + return DOCH_OK; +} + +/*----------------------------------------------------------------------*/ +/* D O C H A d d P a r t i t i o n */ +/* */ +/* Adds a partition */ +/* The new partition is created on existing un-formatted disk capacity */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irData : Pointer to DOCH_PartitionFormatInfoAPI struct */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_ADD_PARTITION */ +/* */ +/* Returns: */ +/* irCount : Number of the created partition */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHAddPartitionSingleFloor(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq ioreq2; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_PartitionFormatInfoAPI* partInfo = (DOCH_PartitionFormatInfoAPI*)(ioreq->irData); + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /* Clear partFormatInfo */ + /*----------------------*/ + tffsset(&partFormatInfo, 0, sizeof(DOCH_PartitionFormatInfo)); + + /* Format DOCH_PartitionFormatInfoAPI to DOCH_PartitionFormatInfo */ + /*----------------------------------------------------------------*/ + DOCH_SetBits(&partFormatInfo.dwCommandFlagsOrStatuses, + DOCH_CFSB_FAST_AREA_SIZE_TYPE, + DOCH_CFSO_FAST_AREA_SIZE_TYPE, + partInfo->dwFastAreaSizeType); + + DOCH_SetBits(&partFormatInfo.partitionAttributes1, + DOCH_PA1B_PARTITION_TYPE, + DOCH_PA1O_PARTITION_TYPE, + partInfo->dwPartitionType); + DOCH_SetBits(&partFormatInfo.partitionAttributes1, + DOCH_PA1B_PERFORMANCE_CTRL, + DOCH_PA1O_PERFORMANCE_CTRL, + partInfo->dwPerformanceControl); + DOCH_SetBits(&partFormatInfo.partitionAttributes1, + DOCH_PA1B_PAGE_SIZE_EXP, + DOCH_PA1O_PAGE_SIZE_EXP, + partInfo->dwPageSizeExp); + DOCH_SetBits(&partFormatInfo.partitionAttributes1, + DOCH_PA1B_HASH_TYPE, + DOCH_PA1O_HASH_TYPE, + partInfo->dwHashType); + + DOCH_SetBits(&partFormatInfo.partitionAttributes2, + DOCH_PA2B_PROTECTION_TYPE, + DOCH_PA2O_PROTECTION_TYPE, + partInfo->dwProtectionType); + DOCH_SetBits(&partFormatInfo.partitionAttributes2, + DOCH_PA2B_USER_MODE, + DOCH_PA2O_USER_MODE, + partInfo->dwUserAccessMode); + DOCH_SetBits(&partFormatInfo.partitionAttributes2, + DOCH_PA2B_GUEST_MODE, + DOCH_PA2O_GUEST_MODE, + partInfo->dwGuestAccessMode); + DOCH_SetBits(&partFormatInfo.partitionAttributes2, + DOCH_PA2B_MASTER_CTRL, + DOCH_PA2O_MASTER_CTRL, + partInfo->dwMasterControl); + DOCH_SetBits(&partFormatInfo.partitionAttributes2, + DOCH_PA2B_ENCRYPT_TYPE, + DOCH_PA2O_ENCRYPT_TYPE, + partInfo->dwEncryptionType); + DOCH_SetBits(&partFormatInfo.partitionAttributes2, + DOCH_PA2B_OTP_BIT, + DOCH_PA2O_OTP_BIT, + partInfo->dwOtpEnabled); + DOCH_SetBits(&partFormatInfo.partitionAttributes2, + DOCH_PA2B_LOCK_CTRL, + DOCH_PA2O_LOCK_CTRL, + partInfo->dwLockControl); + DOCH_SetBits(&partFormatInfo.partitionAttributes2, + DOCH_PA2B_MAX_AUTH_ATTEMPTS, + DOCH_PA2O_MAX_AUTH_ATTEMPTS, + partInfo->dwMaxNumOfAuthAttempts); + + partFormatInfo.nPartitionSize = partInfo->nPartitionSize; + partFormatInfo.nFastAreaSize = partInfo->nFastAreaSize; + partFormatInfo.wFastAreaFactor = partInfo->wFastAreaFactor; + tffscpy(partFormatInfo.bPasskey, &partInfo->bPasskey, sizeof(partFormatInfo.bPasskey)); + + #ifdef DOCH_BIG_ENDIAN + /*In case of a BIG ENDIAN host CPU, reorder bytes in 16 and 32 Bit variables*/ + partFormatInfo.dwCommandFlagsOrStatuses = be_FLDword((FLByte*)&partFormatInfo.dwCommandFlagsOrStatuses); + partFormatInfo.partitionAttributes1 = be_FLDword((FLByte*)&partFormatInfo.partitionAttributes1); + partFormatInfo.partitionAttributes2 = be_FLDword((FLByte*)&partFormatInfo.partitionAttributes2); + partFormatInfo.nPartitionSize = be_FLDword((FLByte*)&partFormatInfo.nPartitionSize); + partFormatInfo.nFastAreaSize = be_FLDword((FLByte*)&partFormatInfo.nFastAreaSize); + partFormatInfo.wFastAreaFactor = be_FLWord ((FLByte*)&partFormatInfo.wFastAreaFactor); + #endif /*DOCH_BIG_ENDIAN*/ + + /* Update ATA register values */ + /*----------------------------*/ + in_regs.bFeaturesError = DOCH_ADD_PARTITION; + in_regs.bSectorCount = 0; + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_SELECT_DEV(pdev->bAtaDevNum); + in_regs.bCommandStatus = DOCH_VSCMD_PARTITION_MANAGEMENT; + + /* Activate ATA command */ + /*----------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + &partFormatInfo, + sizeof(DOCH_PartitionFormatInfo) / DOCH_SECTOR_SIZE); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHAddPartitionSingleFloor(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d\r\n"), rc, pdev->bAtaDevNum)); + + return DOCH_GeneralFailure; + } + + pdev->wTotalNumOfPartitions = 0; + tffsset(&ioreq2, 0, sizeof(ioreq2)); + DOCH_SET_SOCKET_TO_IOREQ_HANDLE(&ioreq2, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + ioreq2.irData = &diskOnChipDeviceInfo; + rc = DOCHIdentifyDiskOnChipDevice(&ioreq2); + if(rc != DOCH_OK) + return rc; + + pdev->wTotalNumOfPartitions = diskOnChipDeviceInfo.wTotalNumOfPartitions; + + /* Output */ + /*--------*/ + ioreq->irCount = out_regs.bSectorCount; + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHAddPartitionSingleFloor(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d \r\n"), rc,pdev->bAtaDevNum)); + + return DOCH_GeneralFailure; + } +} + +DOCH_Error DOCHAddPartition(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq ioreq2; + DOCH_PartitionFormatInfoAPI* partInfo = (DOCH_PartitionFormatInfoAPI*)(ioreq->irData); + DOCH_Socket* pdev; + FLDword reqSize = partInfo->nPartitionSize; + FLDword tempPartNum = 0; + FLBoolean dev0MightBeFull = FALSE; + FLByte tempLastPartOnDev0 = 0; + FLByte origDevNum; + FLByte partialDev0Part; + DOCH_DeviceInfo tempDOCDI; + + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + origDevNum = pdev->bAtaDevNum; + + /*If 2nd floor is already active - perform on device1*/ + /*===================================================*/ + if((pdev->sSpanData.secondFloorActive) && (pdev->wNumOfDevices > 1)) + { + pdev->bAtaDevNum = 1; + rc = DOCHAddPartitionSingleFloor(ioreq); + pdev->bAtaDevNum = origDevNum; + + /*Update returned partition number*/ + ioreq->irCount += (pdev->sSpanData.bLastPartitionOnDev0); + + if(pdev->sSpanData.bLastDev0PartSpanned) + ioreq->irCount -= 1; + + return rc; + } + + /*If requested size = 0, Add to both Dev0 and Dev1*/ + /*================================================*/ + /*Try adding to Dev0 with size=0*/ + + + if(reqSize == 0) + { + /*Dev0*/ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + /* if there are two floors and fast area was specified in percents + fast area requested might exceed first floor -must be translated to sectors*/ + if(((pdev->wNumOfDevices > 1)) + &&(partInfo->dwFastAreaSizeType==DOCH_FAST_AREA_TYPE_PERCENT) + && (partInfo->nFastAreaSize)&& (partInfo->nFastAreaSize < 100)) + { + /* Cannot add spanned partition with requested fast area specified in percents */ + DBG_PRINT_ERR(FLZONE_API, "DOCHAddPartition(): Cannot add spanned partition with requested fast area specified in percents\r\n"); + return DOCH_GeneralFailure; + + } + ioreq2.irData = ioreq->irData; + rc = DOCHAddPartitionSingleFloor(&ioreq2); + partialDev0Part = (FLByte)ioreq2.irCount; + if(rc != DOCH_OK) + { + /* If operation failed with insufficient space, + check the option of fast area problem*/ + if((pdev->wNumOfDevices > 1)&&(partInfo->nFastAreaSize) + &&(partInfo->dwFastAreaSizeType==DOCH_FAST_AREA_TYPE_SECTORS)) + { + /* add partition with 100 percents fast area to dev0*/ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + tffscpy(&partInfoTemp, ioreq->irData, sizeof(partInfoTemp)); + partInfoTemp.dwFastAreaSizeType =DOCH_FAST_AREA_TYPE_PERCENT; + partInfoTemp.nFastAreaSize = 100; + ioreq2.irData = &partInfoTemp; + rc = DOCHAddPartitionSingleFloor(&ioreq2); + partialDev0Part= (FLByte)ioreq2.irCount; + } + if(rc != DOCH_OK) + { + /* If operation failed with insufficient space, + it means last partition that was added filled Dev0 entirely*/ + dev0MightBeFull = TRUE; + tempLastPartOnDev0 = devUserAttr.sdkAttributes.sSpanInfo.bLastPartitionOnDev0; + } + + } + + /*Insert key (in case the partition was read protected)*/ + if(partInfo->dwGuestAccessMode == DOCH_DEVICE_ACCESS_MODE_NONE) + { + tffsset(&ioreq2, 0, sizeof(ioreq2)); + tffsset(&partAccessTemp, 0, sizeof(partAccessTemp)); + + tffscpy(partAccessTemp.bPassword, partInfo->bPasskey, 0x80); + + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (pdev->device[0].wNumOfPartitions-1)); + ioreq2.irData = &partAccessTemp; + + rc = DOCHAccessPartWithPwdSingleFloor(&ioreq2); + if(rc != DOCH_OK) + return rc; + } + + if(!dev0MightBeFull) + { + /*If created partition was IPL:*/ + /*1. Delete all partition on dev1*/ + /*2. Create on Dev1 as well*/ + if((pdev->wNumOfDevices > 1) && (partialDev0Part == 0)) + { + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irData = ioreq->irData; + ioreq2.irLength = 0xFF; + pdev->bAtaDevNum = 1; + rc = DOCHDeletePartitionsSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + if(rc != DOCH_OK) + return rc; + + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irData = ioreq->irData; + pdev->bAtaDevNum = 1; + rc = DOCHAddPartitionSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + if(rc != DOCH_OK) + return rc; + } + + /*Make sure returned partition number is correct*/ + devUserAttr.sdkAttributes.sSpanInfo.bLastPartitionOnDev0 = partialDev0Part; + ioreq->irCount = partialDev0Part; + } + + if(pdev->wNumOfDevices > 1) + { + if(!dev0MightBeFull) + { + /*Get actual size of the newly added partition*/ + tempPartNum = partialDev0Part; + tffsset(&ioreq2, 0, sizeof(ioreq2)); + tffsset(&partitionInfoTemp, 0, sizeof(partitionInfoTemp)); + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, tempPartNum); + ioreq2.irData = &partitionInfoTemp; + rc = DOCHPartitionInfoSingleFloor(&ioreq2); + if(rc != DOCH_OK) + return rc; + } + /*Add User partition to Dev1 with size = 0*/ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + tffscpy(&partInfoTemp, ioreq->irData, sizeof(partInfoTemp)); + /*if dwFastAreaSizeType was in percents than nFastAreaSize must be 100 + therefore no need to change partInfoTemp*/ + /*if dwFastAreaSizeType was in sectors - + check how many fast area sectors are needed*/ + if ((partInfo->nFastAreaSize) && (partInfo->dwFastAreaSizeType!=DOCH_FAST_AREA_TYPE_PERCENT)) + { + if (partInfo->nFastAreaSize >partitionInfoTemp.nFastAreaSize) + { + partInfoTemp.nFastAreaSize= partInfo->nFastAreaSize - partitionInfoTemp.nFastAreaSize; + } + else + { + partInfoTemp.nFastAreaSize =0; + } + } + ioreq2.irData = &partInfoTemp; + pdev->bAtaDevNum = 1; + rc = DOCHAddPartitionSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + if(rc != DOCH_OK) + return rc; + + /*Update span info structure*/ + /*--------------------------*/ + /*Retrieve current attributes*/ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irData = &devUserAttr; + rc = DOCHGetDiskUserAttributes(&ioreq2); + if(rc != DOCH_OK) + return rc; + + /*Set span info*/ + devUserAttr.sdkAttributes.sSpanInfo.bLastDev0PartSpanned = (!dev0MightBeFull);/*TRUE;*/ + devUserAttr.sdkAttributes.sSpanInfo.secondFloorActive = TRUE; + + if(!dev0MightBeFull) + { + devUserAttr.sdkAttributes.sSpanInfo.dwSpanSector = partitionInfoTemp.nPartitionSize; + devUserAttr.sdkAttributes.sSpanInfo.bLastPartitionOnDev0 = + devUserAttr.sdkAttributes.sSpanInfo.numOfSpannedPartitionOnDev0 = (FLByte)(tempPartNum); + } + else + { + devUserAttr.sdkAttributes.sSpanInfo.dwSpanSector = 0; + devUserAttr.sdkAttributes.sSpanInfo.bLastPartitionOnDev0 = tempLastPartOnDev0; + } + + /*Set attributes back to the device*/ + gSDKUpdatesDiskAttributes = DOCH_GLOBAL_BOOL_PATTERN; + rc = DOCHSetDiskUserAttributes(&ioreq2); + gSDKUpdatesDiskAttributes = 0; + if(rc != DOCH_OK) + return rc; + + /*Update pdev as well*/ + tffscpy(&pdev->sSpanData, &devUserAttr.sdkAttributes.sSpanInfo, sizeof(pdev->sSpanData)); + + /* Finally - update number of partitions*/ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irData = &tempDOCDI; + rc = DOCHIdentifyDiskOnChipDevice(&ioreq2); + pdev->wTotalNumOfPartitions = tempDOCDI.wTotalNumOfPartitions; + if(rc != DOCH_OK) + return rc; + } + + return DOCH_OK; + } + + /*Try adding to Dev0*/ + /*==================*/ + rc = DOCHAddPartitionSingleFloor(ioreq); + if(rc == DOCH_OK) + { + devUserAttr.sdkAttributes.sSpanInfo.bLastPartitionOnDev0 = (FLByte)(ioreq->irCount); + + /*If created partition was IPL:*/ + /*1. Delete all partition on dev1*/ + /*2. Create on Dev1 as well*/ + if((pdev->wNumOfDevices > 1) && (ioreq->irCount == 0)) + { + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irData = ioreq->irData; + ioreq2.irLength = 0xFF; + pdev->bAtaDevNum = 1; + rc = DOCHDeletePartitionsSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + if(rc != DOCH_OK) + return rc; + + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irData = ioreq->irData; + pdev->bAtaDevNum = 1; + rc = DOCHAddPartitionSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + if(rc != DOCH_OK) + return rc; + } + + return DOCH_OK; + } + else if(pdev->wNumOfDevices > 1) + { + FLDword secondChunkSize = 0; + FLDword dwSecondChunkFastAreaSize = 0; + FLDword dwSecondChunkFastAreaType = 0 ; + /*If Adding entire size on Dev0 failed*/ + /*====================================*/ + /*Try adding to Dev0 with size=0*/ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + tffscpy(&partInfoTemp, ioreq->irData, sizeof(partInfoTemp)); + partInfoTemp.nPartitionSize = 0; + if((partInfo->dwFastAreaSizeType==DOCH_FAST_AREA_TYPE_PERCENT) && (partInfo->nFastAreaSize < 100)) + { + partInfoTemp.dwFastAreaSizeType = DOCH_FAST_AREA_TYPE_SECTORS; + partInfoTemp.nFastAreaSize = ((partInfo->nPartitionSize/100) * partInfo->nFastAreaSize); + } + + ioreq2.irData = &partInfoTemp; + rc = DOCHAddPartitionSingleFloor(&ioreq2); + partialDev0Part = (FLByte)ioreq2.irCount; + if(rc != DOCH_OK) + { + /*Checking if Fast Area is too big for Dev#0*/ + /*Try adding to Dev0 with size=0 and Fast Area size 100 percent */ + if(partInfo->nFastAreaSize) + { + tffsset(&ioreq2, 0, sizeof(ioreq2)); + tffscpy(&partInfoTemp, ioreq->irData, sizeof(partInfoTemp)); + partInfoTemp.nPartitionSize = 0; + partInfoTemp.dwFastAreaSizeType = DOCH_FAST_AREA_TYPE_PERCENT; + partInfoTemp.nFastAreaSize = 100; + ioreq2.irData = &partInfoTemp; + rc = DOCHAddPartitionSingleFloor(&ioreq2); + partialDev0Part = (FLByte)ioreq2.irCount; + } + if(rc != DOCH_OK) + { + /* If operation failed with insufficient space or there is no Fast Area, + it means last partition that was added filled Dev0 entirely*/ + dev0MightBeFull = TRUE; + tempLastPartOnDev0 = devUserAttr.sdkAttributes.sSpanInfo.bLastPartitionOnDev0; + /*return rc;*/ + } + } + + if(!dev0MightBeFull) + { + /*Insert key (in case the partition was read protected)*/ + if(partInfoTemp.dwGuestAccessMode == DOCH_DEVICE_ACCESS_MODE_NONE) + { + tffsset(&ioreq2, 0, sizeof(ioreq2)); + tffsset(&partAccessTemp, 0, sizeof(partAccessTemp)); + + tffscpy(partAccessTemp.bPassword, partInfoTemp.bPasskey, 0x80); + + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (pdev->device[0].wNumOfPartitions-1)); + ioreq2.irData = &partAccessTemp; + + rc = DOCHAccessPartWithPwdSingleFloor(&ioreq2); + if(rc != DOCH_OK) + return rc; + } + + /*Make sure returned partition number is correct*/ + ioreq->irCount = partialDev0Part; + + /*Get actual size of the newly added partition*/ + tempPartNum = partialDev0Part; + tffsset(&ioreq2, 0, sizeof(ioreq2)); + tffsset(&partitionInfoTemp, 0, sizeof(partitionInfoTemp)); + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, tempPartNum); + ioreq2.irData = &partitionInfoTemp; + rc = DOCHPartitionInfoSingleFloor(&ioreq2); + if(rc != DOCH_OK) + return rc; + /*checking remaining size of fast area for Dev#1*/ + if(partInfo->dwFastAreaSizeType != DOCH_FAST_AREA_TYPE_PERCENT) + { + if(partInfo->nFastAreaSize > partitionInfoTemp.nPartitionSize) + { + dwSecondChunkFastAreaSize = partInfo->nFastAreaSize - partitionInfoTemp.nPartitionSize; + } + else + { + dwSecondChunkFastAreaSize = 0; + } + dwSecondChunkFastAreaType = partInfo->dwFastAreaSizeType; + } + else + { + if(partInfo->nFastAreaSize == 100) + { + dwSecondChunkFastAreaSize = 100; + dwSecondChunkFastAreaType = DOCH_FAST_AREA_TYPE_PERCENT; + } + else + { + dwSecondChunkFastAreaSize = ((partInfo->nFastAreaSize * (partInfo->nPartitionSize/100)) - partitionInfoTemp.nFastAreaSize); + dwSecondChunkFastAreaType = DOCH_FAST_AREA_TYPE_SECTORS; + } + } + secondChunkSize = (reqSize - partitionInfoTemp.nPartitionSize); + } + else + {/*Partition is not spanned - will reside on second floor*/ + secondChunkSize = reqSize; + dwSecondChunkFastAreaSize = partInfo->nFastAreaSize; + dwSecondChunkFastAreaType = partInfo->dwFastAreaSizeType; + } + + /*Try adding to Dev1 with size=secondChunkSize*/ + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + tffscpy(&partInfoTemp, ioreq->irData, sizeof(partInfoTemp)); + partInfoTemp.nPartitionSize = secondChunkSize; + partInfoTemp.nFastAreaSize = dwSecondChunkFastAreaSize; + partInfoTemp.dwFastAreaSizeType = dwSecondChunkFastAreaType; + ioreq2.irData = &partInfoTemp; + + pdev->bAtaDevNum = 1; + rc = DOCHAddPartitionSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + if(rc != DOCH_OK) + return rc; + + /*Update span info structure*/ + /*--------------------------*/ + /*Retrieve current attributes*/ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irData = &devUserAttr; + rc = DOCHGetDiskUserAttributes(&ioreq2); + if(rc != DOCH_OK) + return rc; + + /*Set span info*/ + devUserAttr.sdkAttributes.sSpanInfo.secondFloorActive = TRUE; + + if(!dev0MightBeFull) + { + devUserAttr.sdkAttributes.sSpanInfo.dwSpanSector = partitionInfoTemp.nPartitionSize; + devUserAttr.sdkAttributes.sSpanInfo.bLastPartitionOnDev0 = + devUserAttr.sdkAttributes.sSpanInfo.numOfSpannedPartitionOnDev0 = (FLByte)(tempPartNum); + devUserAttr.sdkAttributes.sSpanInfo.bLastDev0PartSpanned = TRUE; + + } + else + { + devUserAttr.sdkAttributes.sSpanInfo.dwSpanSector = 0; + devUserAttr.sdkAttributes.sSpanInfo.bLastPartitionOnDev0 = tempLastPartOnDev0; + devUserAttr.sdkAttributes.sSpanInfo.bLastDev0PartSpanned = FALSE; + } + + /*Set attributes back to the device*/ + gSDKUpdatesDiskAttributes = DOCH_GLOBAL_BOOL_PATTERN; + rc = DOCHSetDiskUserAttributes(&ioreq2); + gSDKUpdatesDiskAttributes = 0; + if(rc != DOCH_OK) + return rc; + + /*Update pdev as well*/ + tffscpy(&pdev->sSpanData, &devUserAttr.sdkAttributes.sSpanInfo, sizeof(pdev->sSpanData)); + + /* Finally - update number of partitions*/ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irData = &tempDOCDI; + rc = DOCHIdentifyDiskOnChipDevice(&ioreq2); + pdev->wTotalNumOfPartitions = tempDOCDI.wTotalNumOfPartitions; + if(rc != DOCH_OK) + return rc; + } + else + { + return DOCH_GeneralFailure; + } + + return DOCH_OK; +} + +/*----------------------------------------------------------------------*/ +/* D O C H U n f o r m a t D e v i c e */ +/* */ +/* Unformats DOCH device. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_DELETE_PARTITIONS */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHUnformatSingleDevice(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq ioreq2; + + /*1. Delete all partitions */ + /*=========================*/ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + DOCH_SET_SOCKET_TO_IOREQ_HANDLE(&ioreq2, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + ioreq2.irCount = 0; + ioreq2.irLength = 0xFF; + ioreq2.irFlags = DOCH_COMPLETE_PARTITION_DELETE; + + rc = DOCHDeletePartitions(&ioreq2); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHUnformatDevice(): DOCHDeletePartitions() failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return rc; + } + + /*2. Delete Disk Attributes */ + /*==========================*/ + tffsset(¤tAttributes, 0, sizeof(currentAttributes)); + tffsset(&ioreq2, 0, sizeof(ioreq2)); + DOCH_SET_SOCKET_TO_IOREQ_HANDLE(&ioreq2, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + ioreq2.irData = currentAttributes; + + gSDKUpdatesDiskAttributes = DOCH_GLOBAL_BOOL_PATTERN; + rc = DOCHSetDiskUserAttributes(&ioreq2); + gSDKUpdatesDiskAttributes = 0; + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHUnformatDevice(): DOCHSetDiskUserAttributes() failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return rc; + } + + return DOCH_OK; +} + +DOCH_Error DOCHUnformatDevice(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq ioreq2; + DOCH_Socket* pdev; + FLByte origDevNum; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + origDevNum = pdev->bAtaDevNum; + + pdev->bAtaDevNum = 0; + rc = DOCHUnformatSingleDevice(ioreq); + if(rc != DOCH_OK) + { + pdev->bAtaDevNum = origDevNum; + return rc; + } + + if(pdev->wNumOfDevices > 1) + { + pdev->bAtaDevNum = 1; + rc = DOCHUnformatSingleDevice(ioreq); + pdev->bAtaDevNum = 0; + + if(rc != DOCH_OK) + return rc; + } + + /*Update span info structure*/ + /*--------------------------*/ + pdev->bAtaDevNum = 0; + + /*Retrieve current attributes*/ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irData = &devUserAttr; + rc = DOCHGetDiskUserAttributes(&ioreq2); + if(rc != DOCH_OK) + { + pdev->bAtaDevNum = origDevNum; + return rc; + } + + /*Set span info*/ + devUserAttr.sdkAttributes.sSpanInfo.bLastDev0PartSpanned = FALSE; + devUserAttr.sdkAttributes.sSpanInfo.secondFloorActive = FALSE; + devUserAttr.sdkAttributes.sSpanInfo.dwSpanSector = 0; + devUserAttr.sdkAttributes.sSpanInfo.bLastPartitionOnDev0 = + devUserAttr.sdkAttributes.sSpanInfo.numOfSpannedPartitionOnDev0 = 0; + + /*Set attributes back to the device*/ + gSDKUpdatesDiskAttributes = DOCH_GLOBAL_BOOL_PATTERN; + rc = DOCHSetDiskUserAttributes(&ioreq2); + gSDKUpdatesDiskAttributes = 0; + if(rc != DOCH_OK) + { + pdev->bAtaDevNum = origDevNum; + return rc; + } + + /*Update pdev as well*/ + tffscpy(&pdev->sSpanData, &devUserAttr.sdkAttributes.sSpanInfo, sizeof(pdev->sSpanData)); + + pdev->bAtaDevNum = origDevNum; + + return DOCH_OK; +} + + +/*----------------------------------------------------------------------*/ +/* D O C H W r i t e I P L */ +/* */ +/* Writes IPL partition. */ +/* Sets IPL mode and size. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irFlags : DOCH_IPL_MODE_NORMAL_RAM */ +/* DOCH_IPL_MODE_PAGED_RAM */ +/* DOCH_IPL_MODE_VIRTUAL_RAM */ +/* DOCH_IPL_MODE_CS_DELAY */ +/* DOCH_IPL_MODE_ADDRESS_SHIFT_IN_AFFECT */ +/* DOCH_IPL_MODE_ACTIVE_SWAP_BYTES */ +/* DOCH_IPL_MODE_8KB_WINDOW */ +/* DOCH_IPL_WRITE_FIRST_CHUNK */ +/* irCount : Max IPL size */ +/* Up to 32KB for Normal Mode */ +/* Up to 128KB for Virtual Mode */ +/* Up to 256KB for Paged Mode */ +/* irLength : Current chunk length (in sectors) */ +/* irData : Pointer to user buffer (length defined by */ +/* irLength) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* DOCH_VSCMD_WRITE_PARTITION */ +/* ATA sub-command: */ +/* DOCH_SET_CUSTOM_PARAM */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHWriteIPLSingleFloor(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq ioreq2; + FLBoolean firstChunk = ((ioreq->irFlags & DOCH_IPL_WRITE_FIRST_CHUNK) == DOCH_IPL_WRITE_FIRST_CHUNK); + DOCH_Socket* pdev; + + FLSDword total_num_of_sectors; + FLSDword sectorNumber; + FLSNative sectors_written_so_far; + FLByte* buf_ptr; + FLSNative buf_offset; + + FLByte deviceNum = 0; + + Addressing_Values_s addr_vals; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + + FLByte operationRetries = 0; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + if(firstChunk && (pdev->bAtaDevNum == 0)) + { + /*1. Set IPL BOOT Mode */ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irCount = DOCH_CP_BOOT_MODE; + ioreq2.irSectorNo = (FLWord)(ioreq->irFlags); + ioreq2.irFlags = DOCH_CUSTOM_PARAM_DEFAULT; + rc = DOCHSetCustomParameter(&ioreq2); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWriteIPLSingleFloor(): DOCHSetCustomParameter(Boot Mode) failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return rc; + } + + /*2. Set IPL MAX Size */ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irCount = DOCH_CP_XIP_MAX_SIZE; + ioreq2.irSectorNo = ioreq->irCount; + ioreq2.irFlags = DOCH_CUSTOM_PARAM_DEFAULT; + rc = DOCHSetCustomParameter(&ioreq2); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWriteIPLSingleFloor(): DOCHSetCustomParameter(XIP Size) failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return rc; + } + + gIPLChunkOffsetInSectors = 0; + } + + /*3. Write chunk of data */ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irData = ioreq->irData; + ioreq2.irSectorNo = gIPLChunkOffsetInSectors; + ioreq2.irSectorCount = ioreq->irLength; + + /*Sector arithmetic*/ + /*-----------------*/ + total_num_of_sectors = ioreq2.irSectorCount; + sectorNumber = ioreq2.irSectorNo; + sectors_written_so_far = 0; + + /*Buffer to write from*/ + /*--------------------*/ + buf_ptr = (FLByte*)ioreq2.irData; + buf_offset = 0; + + deviceNum = pdev->bAtaDevNum; + + /*Sanity Check*/ + /*------------*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(&ioreq2) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + /*Enable interrupts*/ + /*-----------------*/ + pdev->bUseInterrupt = TRUE; + + + /*Set DMA and Burst modes according to request*/ + /*--------------------------------------------*/ + pdev->bUseDMA = (((ioreq2.irFlags & DOCH_USE_DMA) == DOCH_USE_DMA) && + (gIsDMAEnabled == DOCH_GLOBAL_BOOL_PATTERN) && + (DOCH_DMA_CHECK_BUFFER(buf_ptr, total_num_of_sectors))); + + pdev->bUseBurst = ((ioreq2.irFlags & DOCH_USE_BURST) == DOCH_USE_BURST); + + /*Perform write cycles in DOCH_MAX_SECTORS quantities*/ + /*---------------------------------------------------*/ + while(total_num_of_sectors > 0) + { + FLSNative sectors_this_cycle; + + if(total_num_of_sectors > DOCH_MAX_SECTORS) + sectors_this_cycle = DOCH_MAX_SECTORS; + else + sectors_this_cycle = total_num_of_sectors; + +dochWriteRetryPointDev1Only: + +#ifdef CHECK_POWER_ON_EVERY_COMMAND + /* Check if device was reset */ + rc = dochCheckPFSymptom(DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(&ioreq2), deviceNum, TRUE); + if(rc != DOCH_OK) + return rc; +#endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + + /*Perform 1 operation cycle*/ + /*=========================*/ + + /*Set ATA addressing registers*/ + /*---------------------------*/ + DOCH_SET_ATA_ADDRESS_VALUES(addr_vals, sectorNumber, deviceNum); + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(&ioreq2); + if(sectors_this_cycle < DOCH_MAX_SECTORS) + in_regs.bSectorCount = sectors_this_cycle; + else + in_regs.bSectorCount = 0; /*DOCH_MAX_SECTORS*/ + + in_regs.bSectorNumber = addr_vals.bSecNum; + in_regs.bCylLow = addr_vals.bCylLow; + in_regs.bCylHigh = addr_vals.bCylHi; + in_regs.bDriveHead = addr_vals.bDevHead; + in_regs.bCommandStatus = DOCH_VSCMD_WRITE_PARTITION; + + /*Activate ATA command*/ + /*--------------------*/ + #ifdef DOCH_DMA_CONFIG + DOCH_OPEN_DMA_CHANNEL + #endif /*DOCH_DMA_CONFIG*/ + + /*Perform ATA command*/ + rc = io_output (pdev, deviceNum, &in_regs, (void*)(&buf_ptr[buf_offset]), sectors_this_cycle); + + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWriteIPLSingleFloor(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device num: %d\r\n"), rc,pdev->bAtaDevNum)); + + rc= get_out_registers(pdev, deviceNum, &out_regs); + + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWriteIPLSingleFloor(): failed with status(retrieved from out register): "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d \r\n"), rc , deviceNum)); + + if( ((rc & DOCH_ATA_ERROR_ADDRESS_MARK_NOT_FOUND) == DOCH_ATA_ERROR_ADDRESS_MARK_NOT_FOUND) && + (operationRetries++ < 4) + ) + goto dochWriteRetryPointDev1Only; + + /*Disable interrupts*/ + /*------------------*/ + pdev->bUseInterrupt = FALSE; + + /*Cancel DMA and Burst modes*/ + /*--------------------------*/ + pdev->bUseDMA = FALSE; + pdev->bUseBurst = FALSE; + + pdev->bAtaDevNum = 0; + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else if((rc & DOCH_ATA_ERROR_ID_NOT_FOUND) == DOCH_ATA_ERROR_ID_NOT_FOUND) + return DOCH_PartitionLimitExceeded; + else + return DOCH_GeneralFailure; + } + } + + /*Update feedback values*/ + /*----------------------*/ + sectors_written_so_far += sectors_this_cycle; + + /*For next possible cycle*/ + /*-----------------------*/ + sectorNumber += sectors_this_cycle; + total_num_of_sectors -= sectors_this_cycle; + buf_offset += sectors_this_cycle * DOCH_SECTOR_SIZE; + + #ifdef CHECK_POWER_ON_EVERY_COMMAND + /* Check if device was reset */ + rc = dochCheckPFSymptom(DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(&ioreq2), deviceNum, FALSE); + if(rc != DOCH_OK) + return rc; + #endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + } + + /*Disable interrupts*/ + /*------------------*/ + pdev->bUseInterrupt = FALSE; + + /*Cancel DMA and Burst modes*/ + /*--------------------------*/ + pdev->bUseDMA = FALSE; + pdev->bUseBurst = FALSE; + + +#if 0 /*Cant verify IPL writing - IPL must be written continuosly, without read operations in between write operations*/ + + /*If verify was define, perform verify operation with same parameters*/ + /*-------------------------------------------------------------------*/ + if(gDochVerifyWrite[DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(&ioreq2)] == DOCH_GLOBAL_BOOL_PATTERN) + { + IOreq ioreq3; + FLByte* verBufOrig; + FLByte i; + + tffsset(&ioreq3, 0, sizeof(ioreq3)); + tffscpy(&ioreq3.irHandle, &ioreq2.irHandle, sizeof(ioreq3.irHandle)); + ioreq3.irData = verifyBuf; + verBufOrig = (FLByte*)(ioreq2.irData); + + for(i=0; ibAtaDevNum)); + + return rc; + } + + if((pdev->bAtaDevNum == 1) || (pdev->wNumOfDevices == 1)) + gIPLChunkOffsetInSectors += ioreq->irLength; + + return rc; +} + +DOCH_Error DOCHWriteIPL(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + pdev->bAtaDevNum = 0; + rc = DOCHWriteIPLSingleFloor(ioreq); + if(rc != DOCH_OK) + return rc; + + if(pdev->wNumOfDevices > 1) + { + pdev->bAtaDevNum = 1; + rc = DOCHWriteIPLSingleFloor(ioreq); + pdev->bAtaDevNum = 0; + } + + return rc; +} + +/*----------------------------------------------------------------------*/ +/* f l D O C H R e a d I P L */ +/* */ +/* Read specified sectors from IPL partition. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : First sector to read */ +/* irLength : Number of sectors to read */ +/* irData : Pointer to user buffer (length defined by */ +/* irLength) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* DOCH_VSCMD_WRITE_PARTITION */ +/* ATA sub-command: */ +/* DOCH_SET_CUSTOM_PARAM */ +/* */ +/* Returns: */ +/* irFlags : DOCH_IPL_MODE_NORMAL_RAM */ +/* DOCH_IPL_MODE_PAGED_RAM */ +/* DOCH_IPL_MODE_VIRTUAL_RAM */ +/* DOCH_IPL_MODE_CS_DELAY */ +/* DOCH_IPL_MODE_ADDRESS_SHIFT_IN_AFFECT */ +/* DOCH_IPL_MODE_ACTIVE_SWAP_BYTES */ +/* DOCH_IPL_MODE_8KB_WINDOW */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHReadIPL(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq ioreq2; + + tffsset(&ioreq2, 0, sizeof(ioreq2)); + DOCH_SET_SOCKET_TO_IOREQ_HANDLE(&ioreq2, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + ioreq2.irData = ioreq->irData; + ioreq2.irSectorNo = ioreq->irCount; + ioreq2.irSectorCount = ioreq->irLength; + + /*1. Retrieve IPL data */ + rc = DOCHReadPartitionSectors(&ioreq2); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHReadIPL(): DOCHReadPartitionSectors() failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return rc; + } + + /*2. Retrieve IPL Mode */ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irCount = DOCH_CP_BOOT_MODE; + ioreq2.irFlags = DOCH_CUSTOM_PARAM_DEFAULT; + rc = DOCHGetCustomParameter(&ioreq2); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHReadIPL(): DOCHGetCustomParameter() failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return rc; + } + + ioreq->irFlags = ioreq2.irLength; + + return DOCH_OK; +} + +/*----------------------------------------------------------------------*/ +/*D O C H R e a d P a r t i t i o n S e c t o r s S i n g l e F l o o r */ +/* */ +/* Reads sectors by sector no from a specific partition */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Address of user buffer to read into */ +/* irSectorNo : First sector no. to read. */ +/* irSectorCount : Number of consecutive sectors to read */ +/* irFlags : DOCH_USE_DMA */ +/* DOCH_USE_BURST */ +/* Note: 4 methods of data transfer are */ +/* available: */ +/* Normal transfer */ +/* DMA transfer */ +/* Burst transfer */ +/* DMA & Burst transfer */ +/* pdev->bAtaDevNum : Floor number */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_READ_PARTITION */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors NOT read (in case of an */ +/* error - this number may not be accurate) */ +/*----------------------------------------------------------------------*/ +static DOCH_Error DOCHReadPartitionSectorsSingleFloor(IOreq* ioreq) +{ + /*parameters*/ + DOCH_Error rc = DOCH_OK; + DOCH_Socket* pdev; + FLByte socketNum =DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq); + FLByte deviceNum = 0; + + /*loop and feedback variables*/ + FLSDword total_num_of_sectors; + FLSDword sectorNumber; + FLSNative sectors_read_so_far; + FLByte* buf_ptr; + FLSNative buf_offset; + + /*internal data structures*/ + DOCH_Registers in_regs; + DOCH_Registers out_regs; + Addressing_Values_s addr_vals; + + DOCH_get_socket(pdev, socketNum); + + /* General sequence: + 1. Sector arithmetic + 2. Setting buffer + 3. Sanity Check + 4. handle DMA, Burst, Interrupts + 5. Read sectors in DOCH_MAX_SECTORS quantities + 5.1 Set ATA addressing registers + 5.2 Update ATA register values + 5.3 Activate ATA command + 5.4 Update feedback values + 5.5 Update loop variables for next possible cycle + Disable interrupts + 6. Disable DMA,Burst and interrupts + 7. Return actual number of read sectors + */ + + + /*1. Sector arithmetic*/ + /*--------------------*/ + total_num_of_sectors = ioreq->irSectorCount; + sectorNumber = ioreq->irSectorNo; + sectors_read_so_far = 0; + + /*2. Setting buffer*/ + /*-----------------*/ + buf_ptr = (FLByte*)ioreq->irData; + buf_offset = 0; + + deviceNum = pdev->bAtaDevNum; + + /*3. Sanity Check */ + /*----------------*/ + + /*Check if Partition exceeds number of existing partitions*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + /*If a negative number of sectors was requested - return error*/ + if(total_num_of_sectors < 0) + return DOCH_BadParameter; + + /* 4. handle DMA, Burst, Interrupts */ + /*------------------------------------*/ + /*Set DMA and Burst modes according to request*/ + pdev->bUseDMA = (((ioreq->irFlags & DOCH_USE_DMA) == DOCH_USE_DMA) && + (gIsDMAEnabled == DOCH_GLOBAL_BOOL_PATTERN) && + (DOCH_DMA_CHECK_BUFFER(buf_ptr, total_num_of_sectors))); + + pdev->bUseBurst = ((ioreq->irFlags & DOCH_USE_BURST) == DOCH_USE_BURST); + +#ifdef DOCH_USE_BURST_MODE_READ_ONLY_IN_DMA + if (!pdev->bUseDMA) + { + pdev->bUseBurst= FALSE; + } +#endif /*DOCH_USE_BURST_MODE_READ_ONLY_IN_DMA*/ + + + /*Enable interrupts if DMA is enabled*/ + if(pdev->bUseDMA) + { + pdev->bUseInterrupt = TRUE; + + } + + /*5. Read sectors in DOCH_MAX_SECTORS quantities*/ + /*----------------------------------------------*/ + while(total_num_of_sectors > 0) + { + FLSNative sectors_this_cycle; + + if(total_num_of_sectors > DOCH_MAX_SECTORS) + sectors_this_cycle = DOCH_MAX_SECTORS; + else + sectors_this_cycle = total_num_of_sectors; + +#ifdef CHECK_POWER_ON_EVERY_COMMAND + /* Check if device was reset */ + rc = dochCheckPFSymptom(DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), deviceNum, TRUE); + if(rc != DOCH_OK) + return rc; +#endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + + /*Perform 1 operation cycle*/ + /*=========================*/ + + /*5.1 Set ATA addressing registers*/ + /*--------------------------------*/ + DOCH_SET_ATA_ADDRESS_VALUES(addr_vals, sectorNumber, deviceNum); + + /*5.2 Update ATA register values*/ + /*------------------------------*/ + in_regs.bFeaturesError = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + if(sectors_this_cycle < DOCH_MAX_SECTORS) + in_regs.bSectorCount = sectors_this_cycle; + else + in_regs.bSectorCount = 0; /*DOCH_MAX_SECTORS*/ + + in_regs.bSectorNumber = addr_vals.bSecNum; + in_regs.bCylLow = addr_vals.bCylLow; + in_regs.bCylHigh = addr_vals.bCylHi; + in_regs.bDriveHead = addr_vals.bDevHead; + in_regs.bCommandStatus = DOCH_VSCMD_READ_PARTITION; + + /*5.3 Activate ATA command*/ + /*------------------------*/ + #ifdef DOCH_DMA_CONFIG + DOCH_OPEN_DMA_CHANNEL + #endif /*DOCH_DMA_CONFIG*/ + + /*Perform ATA command*/ + rc = io_input (pdev, deviceNum, &in_regs, (void*)(&buf_ptr[buf_offset]), sectors_this_cycle); + + if(rc != DOCH_OK) + { + DOCH_Error rc2; + DBG_PRINT_ERR(FLZONE_API, "DOCHReadPartitionSectors(): io_input failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + /*Disable DMA,Burst, interrupts */ + /*-----------------------------*/ + pdev->bUseInterrupt = FALSE; + pdev->bUseDMA = FALSE; + pdev->bUseBurst = FALSE; + +#ifdef CHECK_POWER_ON_EVERY_COMMAND + /* Check if device was reset */ + rc2 = dochCheckPFSymptom(DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), deviceNum, FALSE); + if(rc2 != DOCH_OK) + return rc2; +#endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + + if(rc == DOCH_TimedOut) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHReadPartitionSectors(): io_input returned DOCH_TimedOut! \r\n "); + return rc; + } + + rc2 = get_out_registers(pdev, deviceNum, &out_regs); + + if(rc2 != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHReadPartitionSectors(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc2)); + + if((rc2 & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else if((rc2 & DOCH_ATA_ERROR_ID_NOT_FOUND) == DOCH_ATA_ERROR_ID_NOT_FOUND) + return DOCH_PartitionLimitExceeded; + else + return DOCH_GeneralFailure; + } + + return rc; + } + + /*5.4 Update feedback values*/ + /*--------------------------*/ + sectors_read_so_far += sectors_this_cycle; + + /*5.5 Update loop variables for next possible cycle*/ + /*-------------------------------------------------*/ + sectorNumber += sectors_this_cycle; + total_num_of_sectors -= sectors_this_cycle; + buf_offset += sectors_this_cycle * DOCH_SECTOR_SIZE; + + #ifdef CHECK_POWER_ON_EVERY_COMMAND + /* Check if device was reset */ + rc = dochCheckPFSymptom(DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), deviceNum, FALSE); + if(rc != DOCH_OK) + return rc; + #endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + } /* end of loop */ + + /*6. Disable DMA,Burst and interrupts*/ + /*-----------------------------------*/ + pdev->bUseInterrupt = FALSE; + pdev->bUseDMA = FALSE; + pdev->bUseBurst = FALSE; + + + /*7. Return actual number of read sectors*/ + /*---------------------------------------*/ + ioreq->irSectorCount = sectors_read_so_far; + + return rc; +} + +/*----------------------------------------------------------------------*/ +/* D O C H R e a d P a r t i t i o n S e c t o r s */ +/* */ +/* Reads sectors by sector no from a specific partition */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Address of user buffer to read into */ +/* irSectorNo : First sector no. to read. */ +/* irSectorCount : Number of consecutive sectors to read */ +/* irFlags : DOCH_USE_DMA */ +/* DOCH_USE_BURST */ +/* Note: 4 methods of data transfer are */ +/* available: */ +/* Normal transfer */ +/* DMA transfer */ +/* Burst transfer */ +/* DMA & Burst transfer */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_READ_PARTITION */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors NOT read (in case of an */ +/* error - this number may not be accurate) */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHReadPartitionSectors(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + DOCH_Socket* pdev; + FLByte partNum = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + if(pdev == NULL) + return DOCH_AdapterNotFound; + + /*If partition resides ENTIRELY on Dev0*/ + /*=====================================*/ + if(DOCH_PARTITION_ON_DEV0) + { + pdev->bAtaDevNum=0; + rc= DOCHReadPartitionSectorsSingleFloor(ioreq); + if (rc!=DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHReadPartitionSectors(): DOCHReadPartitionSectorsSingleFloor returned status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + DBG_PRINT_ERR(FLZONE_API, "DOCHReadPartitionSectors(): Failure on partition that resides ENTIRELY on Dev0 "); + } + return rc; + } + + /*If partition resides ENTIRELY on Dev1*/ + /*=====================================*/ + if(DOCH_PARTITION_ON_DEV1) + { + IOreq ioreq2; + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + + if(pdev->sSpanData.bLastDev0PartSpanned) + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0 + 1)); + else + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0)); + + pdev->bAtaDevNum = 1; + + rc= DOCHReadPartitionSectorsSingleFloor(&ioreq2); + if (rc!=DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHReadPartitionSectors(): DOCHReadPartitionSectorsSingleFloor returned status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + DBG_PRINT_ERR(FLZONE_API, "DOCHReadPartitionSectors(): Failure on partition that resides ENTIRELY on Dev1 "); + } + ioreq->irSectorCount =ioreq2.irSectorCount; + pdev->bAtaDevNum = 0; + return rc; + } + + /*If partition is spanned - collect both infos and combine*/ + /*========================================================*/ + if(DOCH_PARTITION_IS_SPANNED) + { + IOreq ioreq2; + FLDword sectorsToReadFromFirstChunk; + FLDword sectorsToReadFromSecondChunk; + + /*irLength => First sector to read*/ + /*irCount => Number of sectors to read*/ + if( ((FLDword)((ioreq->irLength + ioreq->irCount))) > pdev->sSpanData.dwSpanSector) + { + if(((FLDword)ioreq->irLength) >= pdev->sSpanData.dwSpanSector) + { + sectorsToReadFromFirstChunk = 0; + sectorsToReadFromSecondChunk = ioreq->irCount; + + } + else + { + sectorsToReadFromFirstChunk = (pdev->sSpanData.dwSpanSector - ioreq->irLength); + sectorsToReadFromSecondChunk = (ioreq->irCount - sectorsToReadFromFirstChunk); + } + } + else + { + sectorsToReadFromFirstChunk = ioreq->irCount; + sectorsToReadFromSecondChunk = 0; + } + + ioreq->irSectorCount =0; + + /*Read first chunk from Dev0*/ + /*--------------------------*/ + if(sectorsToReadFromFirstChunk > 0) + { + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + ioreq2.irCount = sectorsToReadFromFirstChunk; + pdev->bAtaDevNum = 0; + rc= DOCHReadPartitionSectorsSingleFloor(&ioreq2); + if (rc!=DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHReadPartitionSectors(): DOCHReadPartitionSectorsSingleFloor returned status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + DBG_PRINT_ERR(FLZONE_API, "DOCHReadPartitionSectors(): Failure on spanned partition when reading chunk from Dev0 "); + return rc; + } + ioreq->irSectorCount =ioreq2.irSectorCount; + + } + + /*Read 2nd chunk from Dev1*/ + /*------------------------*/ + if(sectorsToReadFromSecondChunk > 0) + { + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + ioreq2.irCount = sectorsToReadFromSecondChunk; + + if(sectorsToReadFromFirstChunk > 0) + ioreq2.irLength = 0; + else + { + ioreq2.irLength = (ioreq->irLength - pdev->sSpanData.dwSpanSector); + } + ioreq2.irData = (FLByte*)ioreq->irData + (sectorsToReadFromFirstChunk<sSpanData.numOfSpannedPartitionOnDev0 + 1)); + + pdev->bAtaDevNum = 1; + + rc= DOCHReadPartitionSectorsSingleFloor(&ioreq2); + if (rc!=DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHReadPartitionSectors(): DOCHReadPartitionSectorsSingleFloor returned status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + DBG_PRINT_ERR(FLZONE_API, "DOCHReadPartitionSectors(): Failure on spanned partition when reading chunk from Dev1 "); + } + pdev->bAtaDevNum = 0; + ioreq->irSectorCount +=ioreq2.irSectorCount; + return rc; + } + } + + return DOCH_OK; +} + +/*-----------------------------------------------------------------------*/ +/*D O C H W r i t e P a r t i t i o n S e c t o r s S i n g l e F l o o r*/ +/* */ +/* Writes sectors by sector no to a specific partition */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Address of user buffer to write from */ +/* irSectorNo : First sector no. to write */ +/* irSectorCount : Number of consecutive sectors to write */ +/* irFlags : DOCH_USE_DMA */ +/* DOCH_USE_BURST */ +/* Note: 4 methods of data transfer are */ +/* available: */ +/* Normal transfer */ +/* DMA transfer */ +/* Burst transfer */ +/* DMA & Burst transfer */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_WRITE_PARTITION */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors NOT read (in case of an */ +/* error - this number may not be accurate) */ +/*-----------------------------------------------------------------------*/ +DOCH_Error DOCHWritePartitionSectorsSingleFloor(IOreq* ioreq) +{ + /* parameters */ + FLByte partNum = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + FLByte socketNum=DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq); + DOCH_Error rc = DOCH_OK; + FLByte deviceNum = 0; + DOCH_Socket* pdev; + + /*loop and feedback variables*/ + FLSDword total_num_of_sectors; + FLSDword sectorNumber; + FLSNative sectors_written_so_far; + FLByte* buf_ptr; + FLSNative buf_offset; + FLByte operationRetries = 0; + + /*internal data structures*/ + Addressing_Values_s addr_vals; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + +#ifdef FL_VERIFY_WRITE + IOreq ioreq2; + FLByte* verBufOrig; + register int i; +#endif /*FL_VERIFY_WRITE*/ + + /* General sequence: + 1. Sector arithmetic + 2. Setting buffer + 3. Sanity Check + 4. handle DMA, Burst and Interrupts + 5. Perform write cycles in DOCH_MAX_SECTORS quantities + 5.1 Set ATA addressing registers + 5.2 Update ATA register values + 5.3 Activate ATA command + 5.4 Update feedback values + 5.5 Update loop variables for next possible cycle + 6. Disable DMA and Burst and Interrupts. + 7. If verify was define, perform verify operation with same parameters + 8. Return actual number of written sectors + */ + + DOCH_get_socket(pdev, socketNum); + deviceNum = pdev->bAtaDevNum; + + + /*1. Sector arithmetic*/ + /*-----------------*/ + total_num_of_sectors = ioreq->irSectorCount; + sectorNumber = ioreq->irSectorNo; + sectors_written_so_far = 0; + + /*2. Setting Buffer to write from*/ + /*-------------------------------*/ + buf_ptr = (FLByte*)ioreq->irData; + buf_offset = 0; + + + /*3. Sanity Check*/ + /*---------------*/ + if(partNum >= pdev->device[deviceNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + /*4. handle DMA, Burst and Interrupts*/ + /*-----------------------------------*/ + + /*Enable interrupts*/ + pdev->bUseInterrupt = TRUE; + + /*Set DMA and Burst modes according to request*/ + pdev->bUseDMA = (((ioreq->irFlags & DOCH_USE_DMA) == DOCH_USE_DMA) && + (gIsDMAEnabled == DOCH_GLOBAL_BOOL_PATTERN) && + (DOCH_DMA_CHECK_BUFFER(buf_ptr, total_num_of_sectors))); + + pdev->bUseBurst = ((ioreq->irFlags & DOCH_USE_BURST) == DOCH_USE_BURST); + + /*5. Perform write cycles in DOCH_MAX_SECTORS quantities*/ + /*------------------------------------------------------*/ + while(total_num_of_sectors > 0) + { + FLSNative sectors_this_cycle; + + if(total_num_of_sectors > DOCH_MAX_SECTORS) + sectors_this_cycle = DOCH_MAX_SECTORS; + else + sectors_this_cycle = total_num_of_sectors; + +dochWriteRetryPoint: + +#ifdef CHECK_POWER_ON_EVERY_COMMAND + /* Check if device was reset */ + rc = dochCheckPFSymptom(socketNum, deviceNum, TRUE); + if(rc != DOCH_OK) + return rc; +#endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + + /*Perform 1 operation cycle*/ + /*=========================*/ + + /*5.1 Set ATA addressing registers*/ + /*--------------------------------*/ + DOCH_SET_ATA_ADDRESS_VALUES(addr_vals, sectorNumber, deviceNum); + + /*5.2 Update ATA register values*/ + /*------------------------------*/ + in_regs.bFeaturesError = partNum; + if(sectors_this_cycle < DOCH_MAX_SECTORS) + in_regs.bSectorCount = sectors_this_cycle; + else + in_regs.bSectorCount = 0; /*DOCH_MAX_SECTORS*/ + + in_regs.bSectorNumber = addr_vals.bSecNum; + in_regs.bCylLow = addr_vals.bCylLow; + in_regs.bCylHigh = addr_vals.bCylHi; + in_regs.bDriveHead = addr_vals.bDevHead; + in_regs.bCommandStatus = DOCH_VSCMD_WRITE_PARTITION; + + /*5.3 Activate ATA command*/ + /*------------------------*/ + #ifdef DOCH_DMA_CONFIG + DOCH_OPEN_DMA_CHANNEL + #endif /*DOCH_DMA_CONFIG*/ + + /*Perform ATA command*/ + rc = io_output (pdev, deviceNum, &in_regs, (void*)(&buf_ptr[buf_offset]), sectors_this_cycle); + + if(rc != DOCH_OK) + { + DOCH_Error rc2 = DOCH_OK; + + DBG_PRINT_ERR(FLZONE_API, "DOCHWritePartitionSectorsSingleFloor(): io_output returned status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d \r\n"), rc,deviceNum)); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("parameters: irHandle:%d ,irSectorNo:%d, irSectorConut:%d \r\n"), ioreq->irHandle,ioreq->irSectorNo,ioreq->irSectorCount)); + + /* Disable DMA,BURST and interrupts */ + /************************************/ + pdev->bUseInterrupt = FALSE; + pdev->bUseDMA = FALSE; + pdev->bUseBurst = FALSE; + +#ifdef CHECK_POWER_ON_EVERY_COMMAND + /* Check if device was reset */ + rc2 = dochCheckPFSymptom(socketNum, deviceNum, FALSE); + if(rc2 != DOCH_OK) + return rc2; +#endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + + if(rc == DOCH_TimedOut) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWritePartitionSectorsSingleFloor(): io_output returned DOCH_TimedOut! \r\n "); + return rc; + } + + rc2 = get_out_registers(pdev, deviceNum, &out_regs); + + if(rc2 != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWritePartitionSectors(): failed with status (retrieved from register): "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc2)); + + if( ((rc2 & DOCH_ATA_ERROR_ADDRESS_MARK_NOT_FOUND) == DOCH_ATA_ERROR_ADDRESS_MARK_NOT_FOUND) && + (operationRetries++ < 4) + ) + goto dochWriteRetryPoint; + + /*pdev->bAtaDevNum = 0;*/ + + if((rc2 & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else if((rc2 & DOCH_ATA_ERROR_ID_NOT_FOUND) == DOCH_ATA_ERROR_ID_NOT_FOUND) + return DOCH_PartitionLimitExceeded; + else + return DOCH_GeneralFailure; + } + return rc; + } /*rc != DOCH_OK*/ + + /*5.4 Update feedback values*/ + /*--------------------------*/ + sectors_written_so_far += sectors_this_cycle; + + /*5.5 Update loop variables for next possible cycle*/ + /*-------------------------------------------------*/ + sectorNumber += sectors_this_cycle; + total_num_of_sectors -= sectors_this_cycle; + buf_offset += sectors_this_cycle * DOCH_SECTOR_SIZE; + + #ifdef CHECK_POWER_ON_EVERY_COMMAND + /* Check if device was reset */ + rc = dochCheckPFSymptom(socketNum, deviceNum, FALSE); + if(rc != DOCH_OK) + return rc; + #endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + } /* while(total_num_of_sectors > 0) */ + + /*6. Disable DMA and Burst and Interrupts*/ + /*---------------------------------------*/ + pdev->bUseInterrupt = FALSE; + pdev->bUseDMA = FALSE; + pdev->bUseBurst = FALSE; + +#ifdef FL_VERIFY_WRITE + /*7. If verify was define, perform verify operation with same parameters*/ + /*----------------------------------------------------------------------*/ + if(gDochVerifyWrite[socketNum] == DOCH_GLOBAL_BOOL_PATTERN) + { + DBG_PRINT_FLOW(FLZONE_API, "DOCHWritePartitionSectorsSingleFloor(): verify write\r\n"); + tffsset(&ioreq2, 0, sizeof(ioreq2)); + tffscpy(&ioreq2.irHandle, &ioreq->irHandle, sizeof(ioreq2.irHandle)); + ioreq2.irData = verifyBuf; + verBufOrig = (FLByte*)(ioreq->irData); + + for(i=0; iirSectorCount; i++) + { + ioreq2.irSectorCount = 1; + ioreq2.irSectorNo = (ioreq->irSectorNo + i); + rc = DOCHReadPartitionSectorsSingleFloor(&ioreq2); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWritePartitionSectorsSingleFloor(): DOCHReadPartitionSectors() failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d\r\n"), rc,deviceNum)); + + return rc; + } + + if(tffscmp(verifyBuf, verBufOrig, DOCH_SECTOR_SIZE)) + { + DBG_PRINT_ERR(FLZONE_API, "\r\nDOCHWritePartitionSectorsSingleFloor(): Sector "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("#%d device number:%d "), i,deviceNum)); + DBG_PRINT_ERR(FLZONE_API, "Verify failed ! \r\n"); + + return DOCH_WriteFault; + } + + verBufOrig += DOCH_SECTOR_SIZE; + } + } +#endif /*FL_VERIFY_WRITE*/ + /*8. Return actual number of written sectors*/ + /*------------------------------------------*/ + ioreq->irSectorCount = sectors_written_so_far; + + return rc; + +} + +/*----------------------------------------------------------------------*/ +/* D O C H W r i t e P a r t i t i o n S e c t o r s */ +/* */ +/* Writes sectors by sector no to a specific partition */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Address of user buffer to write from */ +/* irSectorNo : First sector no. to write */ +/* irSectorCount : Number of consecutive sectors to write */ +/* irFlags : DOCH_USE_DMA */ +/* DOCH_USE_BURST */ +/* Note: 4 methods of data transfer are */ +/* available: */ +/* Normal transfer */ +/* DMA transfer */ +/* Burst transfer */ +/* DMA & Burst transfer */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_WRITE_PARTITION */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors NOT read (in case of an */ +/* error - this number may not be accurate) */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHWritePartitionSectors(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + DOCH_Socket* pdev; + FLByte partNum = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + if(pdev == NULL) + return DOCH_AdapterNotFound; + + /*If partition resides ENTIRELY on Dev0*/ + /*=====================================*/ + if(DOCH_PARTITION_ON_DEV0) + { + pdev->bAtaDevNum=0; + rc= DOCHWritePartitionSectorsSingleFloor(ioreq); + if (rc!=DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWritePartitionSectors(): DOCHWritePartitionSectorsSingleFloor returned status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + DBG_PRINT_ERR(FLZONE_API, "DOCHWritePartitionSectors(): Failure on partition that resides ENTIRELY on Dev0 "); + } + return rc; + } + + /*If partition resides ENTIRELY on Dev1*/ + /*=====================================*/ + if(DOCH_PARTITION_ON_DEV1) + { + IOreq ioreq2; + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + + if(pdev->sSpanData.bLastDev0PartSpanned) + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0 + 1)); + else + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0)); + + pdev->bAtaDevNum = 1; + rc= DOCHWritePartitionSectorsSingleFloor(&ioreq2); + if (rc!=DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWritePartitionSectors(): DOCHWritePartitionSectorsSingleFloor returned status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + DBG_PRINT_ERR(FLZONE_API, "DOCHWritePartitionSectors(): Failure on partition that resides ENTIRELY on Dev1 "); + } + ioreq->irSectorCount =ioreq2.irSectorCount; + pdev->bAtaDevNum = 0; + return rc; + } + + /*If partition is spanned - collect both infos and combine*/ + /*========================================================*/ + if(DOCH_PARTITION_IS_SPANNED) + { + IOreq ioreq2; + FLDword sectorsToWriteToFirstChunk; + FLDword sectorsToWriteToSecondChunk; + + /*irLength => First sector to read*/ + /*irCount => Number of sectors to read*/ + if( ((FLDword)((ioreq->irLength + ioreq->irCount))) > pdev->sSpanData.dwSpanSector) + { + if(((FLDword)ioreq->irLength) >= pdev->sSpanData.dwSpanSector) + { + sectorsToWriteToFirstChunk = 0; + sectorsToWriteToSecondChunk = ioreq->irCount; + + } + else + { + sectorsToWriteToFirstChunk = (pdev->sSpanData.dwSpanSector - ioreq->irLength); + sectorsToWriteToSecondChunk = (ioreq->irCount - sectorsToWriteToFirstChunk); + } + } + else + { + sectorsToWriteToFirstChunk = ioreq->irCount; + sectorsToWriteToSecondChunk = 0; + } + + ioreq->irSectorCount = 0; + /*Write first chunk to Dev0*/ + /*-------------------------*/ + if(sectorsToWriteToFirstChunk > 0) + { + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + ioreq2.irCount = sectorsToWriteToFirstChunk; + pdev->bAtaDevNum = 0; + rc= DOCHWritePartitionSectorsSingleFloor(&ioreq2); + if (rc!=DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWritePartitionSectors(): DOCHWritePartitionSectorsSingleFloor returned status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + DBG_PRINT_ERR(FLZONE_API, "DOCHWritePartitionSectors(): Failure on spanned partition when writing chunk to Dev0 "); + return rc; + } + ioreq->irSectorCount =ioreq2.irSectorCount; + + }/*end of Write first chunk to Dev0*/ + + /*Write 2nd chunk to Dev1*/ + /*-----------------------*/ + if(sectorsToWriteToSecondChunk > 0) + { + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + ioreq2.irCount = sectorsToWriteToSecondChunk; + + /*Fix first sector to read*/ + if(sectorsToWriteToFirstChunk > 0) + ioreq2.irLength = 0; + else + { + ioreq2.irLength = (ioreq->irLength - pdev->sSpanData.dwSpanSector); + } + + ioreq2.irData = (FLByte*)ioreq->irData + (sectorsToWriteToFirstChunk<sSpanData.numOfSpannedPartitionOnDev0 + 1)); + + pdev->bAtaDevNum = 1; + + rc= DOCHWritePartitionSectorsSingleFloor(&ioreq2); + if (rc!=DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWritePartitionSectors(): DOCHWritePartitionSectorsSingleFloor returned status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + DBG_PRINT_ERR(FLZONE_API, "DOCHWritePartitionSectors(): Failure on spanned partition when writing chunk to Dev1 "); + } + pdev->bAtaDevNum = 0; + ioreq->irSectorCount +=ioreq2.irSectorCount; + return rc; + }/*end of Write 2nd chunk to Dev1*/ + + }/*DOCH_PARTITION_IS_SPANNED*/ + + return DOCH_OK; +} + +/*----------------------------------------------------------------------*/ +/* D O C H W r i t e A n d L o c k */ +/* */ +/* Writes sectors by sector no to a specific partition */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Address of user buffer to write from */ +/* irSectorNo : First sector no. to write */ +/* irSectorCount : Number of consecutive sectors to write */ +/* irFlags : DOCH_USE_DMA */ +/* DOCH_USE_BURST */ +/* Note: 4 methods of data transfer are */ +/* available: */ +/* Normal transfer */ +/* DMA transfer */ +/* Burst transfer */ +/* DMA & Burst transfer */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_WRITE_PARTITION */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors NOT read (in case of an */ +/* error - this number may not be accurate) */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHWriteAndLockSingleFloor(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + DOCH_Socket * pdev; + IOreq ioreq2; + DOCH_Registers out_regs; + + /*Sector arithmetic*/ + /*-----------------*/ + FLSDword total_num_of_sectors = ioreq->irSectorCount; + FLSDword sectorNumber = ioreq->irSectorNo; + FLSNative sectors_written_so_far = 0; + + /*Buffer to write from*/ + /*--------------------*/ + FLByte* buf_ptr = (FLByte*)ioreq->irData; + FLSNative buf_offset = 0; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check if Partition exceeds number of existing partitions*/ + /*--------------------------------------------------------*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + /*If a negative number of sectors was requested - return error*/ + /*------------------------------------------------------------*/ + if(total_num_of_sectors < 0) + return DOCH_BadParameter; + + /*Enable interrupts*/ + /*-----------------*/ + pdev->bUseInterrupt = TRUE; + + + /*Set DMA and Burst modes according to request*/ + /*--------------------------------------------*/ + pdev->bUseDMA = (((ioreq->irFlags & DOCH_USE_DMA) == DOCH_USE_DMA) && + (gIsDMAEnabled == DOCH_GLOBAL_BOOL_PATTERN) && + (DOCH_DMA_CHECK_BUFFER(buf_ptr, total_num_of_sectors))); + + pdev->bUseBurst = ((ioreq->irFlags & DOCH_USE_BURST) == DOCH_USE_BURST); + + /*Write sectors in DOCH_MAX_SECTORS quantities*/ + /*--------------------------------------------*/ + while(total_num_of_sectors > 0) + { + FLSNative sectors_this_cycle; + + if(total_num_of_sectors > DOCH_MAX_SECTORS) + sectors_this_cycle = DOCH_MAX_SECTORS; + else + sectors_this_cycle = total_num_of_sectors; + + rc = performSectorsOperation(DOCH_VSCMD_WRITE_PARTITION, + 0, + pdev, + ioreq, + &out_regs, + sectors_this_cycle, + (FLSNative*)§orNumber, + (FLSNative*)&total_num_of_sectors, + §ors_written_so_far, + &buf_offset, + buf_ptr); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWriteAndLockSingleFloor(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d \r\n"), rc,pdev->bAtaDevNum)); + + /*Disable interrupts*/ + /*------------------*/ + pdev->bUseInterrupt = FALSE; + + /*Cancel DMA and Burst modes*/ + /*--------------------------*/ + pdev->bUseDMA = FALSE; + pdev->bUseBurst = FALSE; + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else if((rc & DOCH_ATA_ERROR_ID_NOT_FOUND) == DOCH_ATA_ERROR_ID_NOT_FOUND) + return DOCH_PartitionLimitExceeded; + else + return DOCH_GeneralFailure; + } + } + + /*Disable interrupts*/ + /*------------------*/ + pdev->bUseInterrupt = FALSE; + + /*Cancel DMA and Burst modes*/ + /*--------------------------*/ + pdev->bUseDMA = FALSE; + pdev->bUseBurst = FALSE; + + /* Now lock the partition as OTP */ + /*-------------------------------*/ + tffsset(&protAPI, 0, sizeof(DOCH_PartitionProtectionAPI)); + tffsset(&ioreq2, 0, sizeof(ioreq2)); + tffscpy(&ioreq2.irHandle, &ioreq->irHandle, sizeof(ioreq2.irHandle)); + ioreq2.irData = &protAPI; + ioreq2.irFlags = DOCH_LOCK_AS_OTP; + rc = DOCHSetParitionProtectionSingleFloor(&ioreq2); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWriteAndLockSingleFloor(): DOCHSetParitionProtection failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d \r\n"), rc, pdev->bAtaDevNum)); + + return rc; + } + + /*Return actual number of written sectors*/ + /*---------------------------------------*/ + ioreq->irSectorCount = sectors_written_so_far; + + return DOCH_OK; +} + +DOCH_Error DOCHWriteAndLock(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq ioreq2; + DOCH_Socket* pdev; + FLByte partNum = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + FLDword sectorsToWriteToFirstChunk; + FLDword sectorsToWriteToSecondChunk; + FLByte* buf; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + /*avoid locking OTP when passed length (in sectors) is zero*/ + if (ioreq->irCount==0) + return DOCH_BadParameter; + + /*If partition resides ENTIRELY on Dev0*/ + /*=====================================*/ + if(DOCH_PARTITION_ON_DEV0) + { + rc = DOCHWriteAndLockSingleFloor(ioreq); + return rc; + } + + /*If partition resides ENTIRELY on Dev1*/ + /*=====================================*/ + if(DOCH_PARTITION_ON_DEV1) + { + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + + if(pdev->sSpanData.bLastDev0PartSpanned) + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0 + 1)); + else + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0)); + + pdev->bAtaDevNum = 1; + rc = DOCHWriteAndLockSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + return rc; + } + + /*If partition is spanned - collect both infos and combine*/ + /*========================================================*/ + if(DOCH_PARTITION_IS_SPANNED) + { + /*irLength => First sector to read*/ + /*irCount => Number of sectors to read*/ + if( ((FLDword)((ioreq->irLength + ioreq->irCount))) > pdev->sSpanData.dwSpanSector) + { + if(((FLDword)ioreq->irLength) >= pdev->sSpanData.dwSpanSector) + { + sectorsToWriteToFirstChunk = 0; + sectorsToWriteToSecondChunk = ioreq->irCount; + + } + else + { + sectorsToWriteToFirstChunk = (pdev->sSpanData.dwSpanSector - ioreq->irLength); + sectorsToWriteToSecondChunk = (ioreq->irCount - sectorsToWriteToFirstChunk); + } + } + else + { + sectorsToWriteToFirstChunk = ioreq->irCount; + sectorsToWriteToSecondChunk = 0; + } + + /*Write first chunk to Dev0*/ + /*-------------------------*/ + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + ioreq2.irCount = sectorsToWriteToFirstChunk; + rc = DOCHWriteAndLockSingleFloor(&ioreq2); + if(rc != DOCH_OK) + return rc; + + /*Write 2nd chunk to Dev1*/ + /*-----------------------*/ + if(sectorsToWriteToSecondChunk > 0) + { + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + ioreq2.irCount = sectorsToWriteToSecondChunk; + ioreq2.irLength = 0; + buf = (FLByte*)ioreq->irData; + ioreq2.irData = buf + (sectorsToWriteToFirstChunk<sSpanData.numOfSpannedPartitionOnDev0 + 1)); + + pdev->bAtaDevNum = 1; + rc = DOCHWriteAndLockSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + if(rc != DOCH_OK) + return rc; + } + } + + return DOCH_OK; +} + +/*----------------------------------------------------------------------*/ +/* D O C H F r e e S e c t o r s */ +/* */ +/* Marks absolute sectors by sector no. as free to be written */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irSectorNo : First sector no. to free */ +/* irSectorCount : Number of consecutive sectors to free */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_ERASE_PARTITION_SECTORS */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors actually deleted */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHFreeSectorsSingleFloor(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + DOCH_Socket * pdev; + DOCH_Registers out_regs; + + /*Sectors arithmetic*/ + /*------------------*/ + FLSDword total_num_of_sectors = ioreq->irSectorCount; + FLSDword sectorNumber = ioreq->irSectorNo; + FLSNative sectors_freed_so_far = 0; + + /*Dummy buffer for use of performSectorsOperation()*/ + /*-------------------------------------------------*/ + FLByte* buf_ptr = NULL; + FLSNative buf_offset = 0; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check if Partition exceeds number of existing partitions*/ + /*--------------------------------------------------------*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + /*If a negative number of sectors was requested - return error*/ + /*------------------------------------------------------------*/ + if(total_num_of_sectors < 0) + return DOCH_BadParameter; + + /*Free sectors in DOCH_MAX_SECTORS quantities*/ + /*--------------------------------------------*/ + while(total_num_of_sectors > 0) + { + FLSNative sectors_this_cycle; + + if(total_num_of_sectors > DOCH_MAX_SECTORS) + sectors_this_cycle = DOCH_MAX_SECTORS; + else + sectors_this_cycle = total_num_of_sectors; + + rc = performSectorsOperation(DOCH_VSCMD_ERASE_PARTITION_SECTORS, + 0, + pdev, + ioreq, + &out_regs, + sectors_this_cycle, + (FLSNative*)§orNumber, + (FLSNative*)&total_num_of_sectors, + §ors_freed_so_far, + &buf_offset, + buf_ptr); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHFreeSectorsSingleFloor(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d\r\n"), rc,pdev->bAtaDevNum)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else if((rc & DOCH_ATA_ERROR_ID_NOT_FOUND) == DOCH_ATA_ERROR_ID_NOT_FOUND) + return DOCH_PartitionLimitExceeded; + else + return DOCH_GeneralFailure; + } + } + + /*Return actual number of freed sectors*/ + /*-------------------------------------*/ + ioreq->irSectorCount = sectors_freed_so_far; + + return DOCH_OK; +} + +DOCH_Error DOCHFreeSectors(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq ioreq2; + DOCH_Socket* pdev; + FLByte partNum = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + FLDword sectorsToDeleteFromFirstChunk; + FLDword sectorsToDeleteFromSecondChunk; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*If partition resides ENTIRELY on Dev0*/ + /*=====================================*/ + if(DOCH_PARTITION_ON_DEV0) + { + rc = DOCHFreeSectorsSingleFloor(ioreq); + return rc; + } + + /*If partition resides ENTIRELY on Dev1*/ + /*=====================================*/ + if(DOCH_PARTITION_ON_DEV1) + { + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + + if(pdev->sSpanData.bLastDev0PartSpanned) + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0 + 1)); + else + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0)); + + pdev->bAtaDevNum = 1; + rc = DOCHFreeSectorsSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + return rc; + } + + /*If partition is spanned - collect both infos and combine*/ + /*========================================================*/ + if(DOCH_PARTITION_IS_SPANNED) + { + /*irLength => First sector to read*/ + /*irCount => Number of sectors to read*/ + if( ((FLDword)((ioreq->irLength + ioreq->irCount))) > pdev->sSpanData.dwSpanSector) + { + if(((FLDword)ioreq->irLength) >= pdev->sSpanData.dwSpanSector) + { + sectorsToDeleteFromFirstChunk = 0; + sectorsToDeleteFromSecondChunk = ioreq->irCount; + + } + else + { + sectorsToDeleteFromFirstChunk = (pdev->sSpanData.dwSpanSector - ioreq->irLength); + sectorsToDeleteFromSecondChunk = (ioreq->irCount - sectorsToDeleteFromFirstChunk); + } + } + else + { + sectorsToDeleteFromFirstChunk = ioreq->irCount; + sectorsToDeleteFromSecondChunk = 0; + } + + /*Free first chunk from Dev0*/ + /*--------------------------*/ + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + ioreq2.irCount = sectorsToDeleteFromFirstChunk; + rc = DOCHFreeSectorsSingleFloor(&ioreq2); + if(rc != DOCH_OK) + return rc; + + /*Free 2nd chunk from Dev1*/ + /*------------------------*/ + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + ioreq2.irCount = sectorsToDeleteFromSecondChunk; + ioreq2.irLength = 0; + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.numOfSpannedPartitionOnDev0 + 1)); + + pdev->bAtaDevNum = 1; + rc = DOCHFreeSectorsSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + if(rc != DOCH_OK) + return rc; + } + + return DOCH_OK; +} + + +/*----------------------------------------------------------------------*/ +/* D O C H W i p e S e c t o r s */ +/* */ +/* Securely erase data in sectors */ +/* */ +/* Parameters: */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irSectorCount : Number of sectors to wipe */ +/* irSectorNumber : Start sector to wipe */ +/* */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_SECURE_ERASE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHWipeSectorsSingleFloor(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + FLDword dwStartSector=ioreq->irSectorNo; + FLDword dwSectorCount=0; + FLDword dwLastSector =(ioreq->irSectorCount + dwStartSector); + FLByte partNum = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check if Partition exceeds number of existing partitions*/ + /*--------------------------------------------------------*/ + if(partNum >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + tffsset(wipeSectorsDev, 0, sizeof(wipeSectorsDev)); + + while (dwStartSector< dwLastSector) + { + if (!(dwStartSector%DOCH_MINIMAL_UNIT_SIZE)) + { + /*aligned to unit*/ + if (dwLastSector-dwStartSector>=DOCH_MINIMAL_UNIT_SIZE) + dwSectorCount= DOCH_MINIMAL_UNIT_SIZE; + else + dwSectorCount=TFFSMIN(DOCH_MINIMAL_PAGE_SIZE,(dwLastSector-dwStartSector)); + } else + { + /*not aligned to unit*/ + if (!(dwStartSector%DOCH_MINIMAL_PAGE_SIZE)) + { /*aligned to page*/ + dwSectorCount=TFFSMIN(DOCH_MINIMAL_PAGE_SIZE,(dwLastSector-dwStartSector)); + } + else + { /*not aligned to page*/ + dwSectorCount=TFFSMIN(DOCH_MINIMAL_PAGE_SIZE,(dwLastSector-dwStartSector)); + dwSectorCount=TFFSMIN((DOCH_MINIMAL_PAGE_SIZE-(dwStartSector%DOCH_MINIMAL_PAGE_SIZE)),dwSectorCount); + } + } + + /* sector to transfer: 1..2 sectors with following layout: */ + /* - 1st 8bytes - reserved as zeros */ + /* - (FLDWord) : First sector to delete */ + /* (FLDWord) : # of sectors to delete */ + /* - (FLDWord) : Second sector to delete */ + /* (FLDWord) : # of sectors to delete */ + /* - ... */ + /* - (FLDWord) : Nth sector to delete */ + /* (FLDWord) : # of sectors to delete */ + /* * Last transaction should have both start */ + /* and length fields set to 0. */ + + toLE4(wipeSectorsDev[2], dwStartSector); + toLE4(wipeSectorsDev[3], dwSectorCount); + + /* Update ATA register values */ + /*----------------------------*/ + in_regs.bFeaturesError = DOCH_SECURE_ERASE; + in_regs.bSectorCount = partNum; + in_regs.bSectorNumber = 1/*one sector to transfer*/; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_SELECT_DEV(pdev->bAtaDevNum); + in_regs.bCommandStatus = DOCH_VSCMD_PARTITION_MANAGEMENT; + + /* Activate ATA command */ + /*----------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + wipeSectorsDev, + 1 /*one sector to transfer*/); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWipeSectorsSingleFloor(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d partition:%d \r\n") + ,rc, pdev->bAtaDevNum,partNum)); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("Parameters: startSector:%d sectorNo:%d \r\n") + ,ioreq->irSectorNo,ioreq->irSectorCount)); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("Failed at: startsector:%d sectorNo:%d \r\n") + ,dwStartSector,dwSectorCount)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else if((rc & DOCH_ATA_ERROR_ID_NOT_FOUND) == DOCH_ATA_ERROR_ID_NOT_FOUND) + return DOCH_PartitionLimitExceeded; + else + return DOCH_GeneralFailure; + } + dwStartSector+=dwSectorCount; + }/*while loop*/ + + return DOCH_OK; +} + + + +/*----------------------------------------------------------------------*/ +/* D O C H W i p e S e c t o r s */ +/* */ +/* Securely erase data in sectors */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irSectorCount : Number of sectors to wipe */ +/* irSectorNumber : Start sector to wipe */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_SECURE_ERASE */ +/* */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ + +DOCH_Error DOCHWipeSectors(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq ioreq2; + FLByte partNum = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + DOCH_Socket* pdev; + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + +#ifndef DOCH_NO_AUTO_WIPE_SECTORS + /*Retrieve device user attributes*/ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + DOCH_SET_SOCKET_TO_IOREQ_HANDLE(&ioreq2, pdev->wSocketNo); + ioreq2.irData = &devUserAttr; + DOCHGetDiskUserAttributes(&ioreq2); + + /* Set secure delete info of both devices, for case of power failure during operation*/ + devUserAttr.sdkAttributes.sSecureDeleteDev1.bPart = partNum; + devUserAttr.sdkAttributes.sSecureDeleteDev1.dwSecureDeleteStartSector = ioreq->irSectorNo; + devUserAttr.sdkAttributes.sSecureDeleteDev1.dwSecureDeleteNumOfSectors = ioreq->irSectorCount; + devUserAttr.sdkAttributes.sSecureDeleteDev1.bOperationRequired = TRUE; + + /*Set attributes back to the device*/ + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + ioreq2.irData = &devUserAttr; + gSDKUpdatesDiskAttributes = DOCH_GLOBAL_BOOL_PATTERN; + rc = DOCHSetDiskUserAttributes(&ioreq2); + gSDKUpdatesDiskAttributes = 0; + if(rc != DOCH_OK) + return rc; +#endif /*DOCH_NO_AUTO_WIPE_SECTORS*/ + + /*If partition resides ENTIRELY on Dev0*/ + /*=====================================*/ + if( (!pdev->sSpanData.secondFloorActive) || (partNum < pdev->sSpanData.bLastPartitionOnDev0) || + ((partNum == pdev->sSpanData.bLastPartitionOnDev0) && (!pdev->sSpanData.bLastDev0PartSpanned)) ) + { + rc = DOCHWipeSectorsSingleFloor(ioreq); + goto InsertCompleteIndication; + } + + /*If partition resides ENTIRELY on Dev1*/ + /*=====================================*/ + if(((pdev->sSpanData.secondFloorActive) && (partNum > pdev->sSpanData.bLastPartitionOnDev0)) + && (pdev->wNumOfDevices > 1)) + { + tffscpy(&ioreq2,ioreq, sizeof(ioreq2)); + if(pdev->sSpanData.bLastDev0PartSpanned) + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0 + 1)); + else + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0)); + + pdev->bAtaDevNum = 1; + rc = DOCHWipeSectorsSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + goto InsertCompleteIndication; + } + + /*If partition is spanned */ + /*=======================*/ + if(((pdev->sSpanData.bLastDev0PartSpanned) && (partNum == pdev->sSpanData.numOfSpannedPartitionOnDev0)) + && (pdev->wNumOfDevices > 1)) + { + + FLDword dwDev1StartSector=0; + FLDword dwDev1SectorCount=0; + + tffsset(&ioreq2,0, sizeof(ioreq2)); /*will contain dev0 information*/ + + /*Split requested sectors to delete to Dev0/Dev1*/ + /*----------------------------------------------*/ + + if((FLDword)ioreq->irSectorNo > pdev->sSpanData.dwSpanSector) + { + /* all required sectors are in dev1*/ + dwDev1StartSector= (FLDword)(ioreq->irSectorNo - pdev->sSpanData.dwSpanSector); + dwDev1SectorCount= (FLDword)ioreq->irSectorCount; + } + else if ((FLDword)(ioreq->irSectorNo + ioreq->irSectorCount) > pdev->sSpanData.dwSpanSector) + { + /* part of the sectors is in dev1*/ + dwDev1SectorCount=(FLDword)(ioreq->irSectorCount - (pdev->sSpanData.dwSpanSector - ioreq->irSectorNo)); + ioreq2.irSectorCount= (FLDword)(pdev->sSpanData.dwSpanSector - ioreq->irSectorNo); + ioreq2.irSectorNo = (FLDword)ioreq->irSectorNo; + }else + { + /* all required sectors are in dev0*/ + ioreq2.irSectorNo = (FLDword)ioreq->irSectorNo; + ioreq2.irSectorCount= (FLDword)ioreq->irSectorCount; + } + + + /*Wipe sectors on Dev0*/ + /*--------------------*/ + if (ioreq2.irSectorCount) + { + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2,partNum); + rc = DOCHWipeSectorsSingleFloor(&ioreq2); + if(rc != DOCH_OK) + goto InsertCompleteIndication;; + } + + + /*Wipe Sectors on Dev1*/ + /*--------------------*/ + if (dwDev1SectorCount) + { + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.numOfSpannedPartitionOnDev0 + 1)); + ioreq2.irSectorNo = (FLDword)dwDev1StartSector; + ioreq2.irSectorCount= (FLDword)dwDev1SectorCount; + + pdev->bAtaDevNum = 1; + rc = DOCHWipeSectorsSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + } + } + +InsertCompleteIndication: + if (rc!=DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWipeSectors(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x partition:%d \r\n"),rc,partNum)); + /* we leave the indication in disk attributes only if + the failure is a result of power loss*/ + if (rc==DOCH_TimedOut || rc==DOCH_DeviceTurnedOff) + return rc; + /* On all other failures- we will not retry erasing */ + } + +#ifndef DOCH_NO_AUTO_WIPE_SECTORS + /* Zero secure delete info */ + devUserAttr.sdkAttributes.sSecureDeleteDev1.bOperationRequired = FALSE; + devUserAttr.sdkAttributes.sSecureDeleteDev1.bPart = 0; + devUserAttr.sdkAttributes.sSecureDeleteDev1.dwSecureDeleteStartSector = 0; + devUserAttr.sdkAttributes.sSecureDeleteDev1.dwSecureDeleteNumOfSectors = 0; + + /*Set attributes back to the device*/ + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + ioreq2.irData = &devUserAttr; + gSDKUpdatesDiskAttributes = DOCH_GLOBAL_BOOL_PATTERN; + rc = DOCHSetDiskUserAttributes(&ioreq2); + gSDKUpdatesDiskAttributes = 0; +#endif /*DOCH_NO_AUTO_WIPE_SECTORS*/ + + return rc; + +} + + + +/*----------------------------------------------------------------------*/ +/* D O C H P r e p a r e F o r W r i t e */ +/* */ +/* Signal to DOCH that these sectors are going to be over-written in */ +/* following write command */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irSectorNo : First sector no. to write */ +/* irSectorCount : Number of consecutive sectors to write */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_OPTIMIZE_PARTITION_SECTORS */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHPrepareForWrite(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + DOCH_Socket * pdev; + DOCH_Registers out_regs; + + /*Sectors arithmetic*/ + /*------------------*/ + FLSDword total_num_of_sectors = ioreq->irSectorCount; + FLSDword sectorNumber = ioreq->irSectorNo; + FLSNative sectorsPreparedSoFar = 0; + + /*Buffer to "write" from*/ + /*----------------------*/ + FLByte* buf_ptr = (FLByte*)ioreq->irData; + FLSNative buf_offset = 0; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check if Partition exceeds number of existing partitions*/ + /*--------------------------------------------------------*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + /*If a negative number of sectors was requested - return error*/ + /*------------------------------------------------------------*/ + if(total_num_of_sectors < 0) + return DOCH_BadParameter; + + rc = performSectorsOperation(DOCH_VSCMD_OPTIMIZE_PARTITION_SECTORS, + PREPARE_FOR_WRITE_OP, + pdev, + ioreq, + &out_regs, + ioreq->irSectorCount, + (FLSNative*)§orNumber, + (FLSNative*)&total_num_of_sectors, + §orsPreparedSoFar, + &buf_offset, + buf_ptr); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHPrepareForWrite(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else if((rc & DOCH_ATA_ERROR_ID_NOT_FOUND) == DOCH_ATA_ERROR_ID_NOT_FOUND) + return DOCH_PartitionLimitExceeded; + else + return DOCH_GeneralFailure; + } + /*If not enough free space - defragment*/ + /*-------------------------------------*/ + if(ioreq->irSectorCount > out_regs.bSectorCount) + { + IOreq ioreq2; + ioreq2.irHandle = ioreq->irHandle; + rc = DOCHOptimizeMedia(&ioreq2); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHPrepareForWrite(): DOCHOptimizeMedia failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return rc; + } + + } + + return DOCH_OK; +} + +#if 0 +/* Flexi-Flash */ + +/*----------------------------------------------------------------------*/ +/* D O C H W r i t e F l e x i F a s t */ +/* */ +/* Flexi-Flash Write Fast */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Address of user buffer to write from */ +/* irSectorNo : First sector no. to write */ +/* irSectorCount : Number of consecutive sectors to write */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_WRITE_FLEXI */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors actually written */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHWriteFlexiFast(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + DOCH_Socket * pdev; + DOCH_Registers out_regs; + FLByte operationRetries = 0; + + /*Sectors arithmetic*/ + /*------------------*/ + FLSDword total_num_of_sectors = ioreq->irSectorCount; + FLSDword sectorNumber = ioreq->irSectorNo; + FLSNative sectors_written_so_far = 0; + + /*Buffer to write from*/ + /*--------------------*/ + FLByte* buf_ptr = (FLByte*)ioreq->irData; + FLSNative buf_offset = 0; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check if Partition exceeds number of existing partitions*/ + /*--------------------------------------------------------*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + /*If a negative number of sectors was requested - return error*/ + /*------------------------------------------------------------*/ + if(total_num_of_sectors < 0) + return DOCH_BadParameter; + + /*Enable interrupts*/ + /*-----------------*/ + pdev->bUseInterrupt = TRUE; + + + /*Write sectors in DOCH_MAX_SECTORS quantities*/ + /*--------------------------------------------*/ + while(total_num_of_sectors > 0) + { + FLSNative sectors_this_cycle; + + if(total_num_of_sectors > DOCH_MAX_SECTORS) + sectors_this_cycle = DOCH_MAX_SECTORS; + else + sectors_this_cycle = total_num_of_sectors; + +dochWriteFlexiRetryPoint: + + rc = performSectorsOperation(DOCH_VSCMD_WRITE_FLEXI, + 0, + pdev, + ioreq, + &out_regs, + sectors_this_cycle, + (FLSNative*)§orNumber, + (FLSNative*)&total_num_of_sectors, + §ors_written_so_far, + &buf_offset, + buf_ptr); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWriteFlexiFast(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + if( ((rc & DOCH_ATA_ERROR_ADDRESS_MARK_NOT_FOUND) == DOCH_ATA_ERROR_ADDRESS_MARK_NOT_FOUND) && + (operationRetries++ < 4) + ) + goto dochWriteFlexiRetryPoint; + + /*Disable interrupts*/ + /*------------------*/ + pdev->bUseInterrupt = FALSE; + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else if((rc & DOCH_ATA_ERROR_ID_NOT_FOUND) == DOCH_ATA_ERROR_ID_NOT_FOUND) + return DOCH_PartitionLimitExceeded; + else + return DOCH_GeneralFailure; + } + } + + /*Disable interrupts*/ + /*------------------*/ + pdev->bUseInterrupt = FALSE; + + /*Return actual number of written sectors*/ + /*---------------------------------------*/ + ioreq->irSectorCount = sectors_written_so_far; + + return DOCH_OK; +} + +/*----------------------------------------------------------------------*/ +/* D O C H W r i t e F l e x i N o r m a l */ +/* */ +/* Flexi-Flash Write Normal */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Address of user buffer to write from */ +/* irSectorNo : First sector no. to write */ +/* irSectorCount : Number of consecutive sectors to write */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_WRITE_FLEXI */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors actually written */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHWriteFlexiNormal(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + DOCH_Socket * pdev; + DOCH_Registers out_regs; + + /*Sectors arithmetic*/ + /*------------------*/ + FLSDword total_num_of_sectors = ioreq->irSectorCount; + FLSDword sectorNumber = ioreq->irSectorNo; + FLSNative sectors_written_so_far = 0; + + /*Buffer to write from*/ + /*--------------------*/ + FLByte* buf_ptr = (FLByte*)ioreq->irData; + FLSNative buf_offset = 0; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check if Partition exceeds number of existing partitions*/ + /*--------------------------------------------------------*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + /*If a negative number of sectors was requested - return error*/ + /*------------------------------------------------------------*/ + if(total_num_of_sectors < 0) + return DOCH_BadParameter; + + /*Enable interrupts*/ + /*-----------------*/ + pdev->bUseInterrupt = TRUE; + + + /*Write sectors in DOCH_MAX_SECTORS quantities*/ + /*--------------------------------------------*/ + while(total_num_of_sectors > 0) + { + FLSNative sectors_this_cycle; + + if(total_num_of_sectors > DOCH_MAX_SECTORS) + sectors_this_cycle = DOCH_MAX_SECTORS; + else + sectors_this_cycle = total_num_of_sectors; + + rc = performSectorsOperation(DOCH_VSCMD_WRITE_FLEXI, + WRITE_NORMAL_OP, + pdev, + ioreq, + &out_regs, + sectors_this_cycle, + (FLSNative*)§orNumber, + (FLSNative*)&total_num_of_sectors, + §ors_written_so_far, + &buf_offset, + buf_ptr); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWriteFlexiNormal(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + /*Disable interrupts*/ + /*------------------*/ + pdev->bUseInterrupt = FALSE; + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else if((rc & DOCH_ATA_ERROR_ID_NOT_FOUND) == DOCH_ATA_ERROR_ID_NOT_FOUND) + return DOCH_PartitionLimitExceeded; + else + return DOCH_GeneralFailure; + } + } + + /*Disable interrupts*/ + /*------------------*/ + pdev->bUseInterrupt = FALSE; + + /*Return actual number of written sectors*/ + /*---------------------------------------*/ + ioreq->irSectorCount = sectors_written_so_far; + + return DOCH_OK; +} + +/*----------------------------------------------------------------------*/ +/* D O C H R e W r i t e F l e x i N o r m a l */ +/* */ +/* Flexi-Flash Re-Write Normal */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Address of user buffer to write from */ +/* irSectorNo : First sector no. to write */ +/* irSectorCount : Number of consecutive sectors to write */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_OPTIMIZE_PARTITION_SECTORS */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors actually re-written */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHReWriteFlexiNormal(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + DOCH_Socket * pdev; + DOCH_Registers out_regs; + + /*Sectors arithmetic*/ + /*------------------*/ + FLSDword total_num_of_sectors = ioreq->irSectorCount; + FLSDword sectorNumber = ioreq->irSectorNo; + FLSNative sectors_written_so_far = 0; + + /*Buffer to rewrite from*/ + /*----------------------*/ + FLByte* buf_ptr = (FLByte*)ioreq->irData; + FLSNative buf_offset = 0; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check if Partition exceeds number of existing partitions*/ + /*--------------------------------------------------------*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + /*If a negative number of sectors was requested - return error*/ + /*------------------------------------------------------------*/ + if(total_num_of_sectors < 0) + return DOCH_BadParameter; + + /*Enable interrupts*/ + /*-----------------*/ + pdev->bUseInterrupt = TRUE; + + + /*Write sectors in DOCH_MAX_SECTORS quantities*/ + /*--------------------------------------------*/ + while(total_num_of_sectors > 0) + { + FLSNative sectors_this_cycle; + + if(total_num_of_sectors > DOCH_MAX_SECTORS) + sectors_this_cycle = DOCH_MAX_SECTORS; + else + sectors_this_cycle = total_num_of_sectors; + + rc = performSectorsOperation(DOCH_VSCMD_OPTIMIZE_PARTITION_SECTORS, + REWRITE_NORMAL_OP, + pdev, + ioreq, + &out_regs, + sectors_this_cycle, + (FLSNative*)§orNumber, + (FLSNative*)&total_num_of_sectors, + §ors_written_so_far, + &buf_offset, + buf_ptr); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHReWriteNormal(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + /*Disable interrupts*/ + /*------------------*/ + pdev->bUseInterrupt = FALSE; + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else if((rc & DOCH_ATA_ERROR_ID_NOT_FOUND) == DOCH_ATA_ERROR_ID_NOT_FOUND) + return DOCH_PartitionLimitExceeded; + else + return DOCH_GeneralFailure; + } + } + + /*Disable interrupts*/ + /*------------------*/ + pdev->bUseInterrupt = FALSE; + + /*Return actual number of written sectors*/ + /*---------------------------------------*/ + ioreq->irSectorCount = sectors_written_so_far; + + return DOCH_OK; +} + + +/*----------------------------------------------------------------------*/ +/* D O C H M a n a g e A t o m i c W r i t e S e q */ +/* */ +/* Manage atomic write sequence per partition */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irCount : DOCH_START_ATOMIC_WRITE */ +/* DOCH_FINISH_ATOMIC_WRITE */ +/* DOCH_ABORT_ATOMIC_WRITE */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_ATOMIC_WRITE_SEQUENCE */ +/* */ +/* Returns: */ +/* irLength : Maximal possible length */ +/* irFlags : Maximal possible length without performance */ +/* loss. */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHManageAtomicWriteSeq(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check if Partition exceeds number of existing partitions*/ + /*--------------------------------------------------------*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_ATOMIC_WRITE_SEQUENCE; + in_regs.bSectorCount = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + in_regs.bSectorNumber = (FLByte)(ioreq->irCount); + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_SELECT_DEV(pdev->bAtaDevNum); + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + /*Return values*/ + /*-------------*/ + ioreq->irLength = out_regs.bSectorCount + (out_regs.bSectorNumber << 8); + ioreq->irFlags = out_regs.bCylLow + (out_regs.bCylHigh << 8); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHManageAtomicWriteSeq(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } + +} + +#endif /*0*/ + + +/*----------------------------------------------------------------------*/ +/* D O C H A c c e s s P a r t W i t h P w d */ +/* */ +/* Insert the protection key in order to remove the protection of the */ +/* specified partition or the entire media */ +/* Partition could be authenticated both by user and master password */ +/* the last successful authentication supersedes the previous one. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irFlags : Authentication Type */ +/* : DOCH_ACCESS_USER_PASSWORD */ +/* DOCH_ACCESS_MASTER_PASSWORD */ +/* DOCH_ACCESS_GATE_KEEPER */ +/* irCount : Authenticate the entire device */ +/* DOCH_ACCESS_ALL_PARTITIONS */ +/* irData : Pointer to an DOCH_PartitionAcessPassword struct */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_ACCESS_CONTROL */ +/* ATA sub-command: */ +/* DOCH_EN_ACCESS_WPWD */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHAccessPartWithPwdSingleFloor(IOreq* ioreq) +{ + DOCH_Error rc; +#ifdef DOCH_BIG_ENDIAN + DOCH_PartitionAcessPassword* partPwdToBig = (DOCH_PartitionAcessPassword*)(ioreq->irData); +#endif /*DOCH_BIG_ENDIAN*/ + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + FLByte sectorCountValue = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check if Partition exceeds number of existing partitions*/ + /*--------------------------------------------------------*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + if(ioreq->irCount == DOCH_ACCESS_ALL_PARTITIONS) + sectorCountValue = 0xFF; + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_EN_ACCESS_WPWD; + in_regs.bSectorCount = sectorCountValue; + in_regs.bSectorNumber = (FLByte)(ioreq->irFlags); + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_SELECT_DEV(pdev->bAtaDevNum); + in_regs.bCommandStatus = DOCH_VSCMD_ACCESS_CONTROL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + ioreq->irData, + (sizeof(DOCH_PartitionAcessPassword) / DOCH_SECTOR_SIZE)); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHAccessPartWithPwdSingleFloor(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d\r\n"), rc,pdev->bAtaDevNum)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else + return DOCH_GeneralFailure; + } +} + +DOCH_Error DOCHAccessPartWithPwd(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq ioreq2; + DOCH_Socket* pdev; + FLByte partNum = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*If partition resides ENTIRELY on Dev0*/ + /*=====================================*/ + if(DOCH_PARTITION_ON_DEV0) + { + rc = DOCHAccessPartWithPwdSingleFloor(ioreq); + return rc; + } + + /*If partition resides ENTIRELY on Dev1*/ + /*=====================================*/ + if(DOCH_PARTITION_ON_DEV1) + { + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + + if(pdev->sSpanData.bLastDev0PartSpanned) + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0 + 1)); + else + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0)); + + pdev->bAtaDevNum = 1; + rc = DOCHAccessPartWithPwdSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + return rc; + } + + /*If partition is spanned - collect both infos and combine*/ + /*========================================================*/ + if(DOCH_PARTITION_IS_SPANNED) + { + /*Set to chunk on Dev0*/ + /*--------------------*/ + rc = DOCHAccessPartWithPwdSingleFloor(ioreq); + if(rc != DOCH_OK) + return rc; + + /*Set to chunk on Dev0*/ + /*--------------------*/ + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.numOfSpannedPartitionOnDev0 + 1)); + + pdev->bAtaDevNum = 1; + rc = DOCHAccessPartWithPwdSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + if(rc != DOCH_OK) + return rc; + } + + return DOCH_OK; +} + +/*----------------------------------------------------------------------*/ +/* D O C H D i s a b l e P a r t A c c e s s */ +/* */ +/* Remove the protection key making the partition protected again */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irCount : Disable access for the entire device */ +/* DOCH_ACCESS_ALL_PARTITIONS */ +/* irFlags : Authentication to withdraw */ +/* DOCH_ACCESS_USER_PASSWORD */ +/* DOCH_ACCESS_MASTER_PASSWORD */ +/* DOCH_ACCESS_GATE_KEEPER */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_ACCESS_CONTROL */ +/* ATA sub-command: */ +/* DOCH_DISABLE_ACCESS */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHDisablePartAccessSingleFloor(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + FLByte sectorCountValue = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check if Partition exceeds number of existing partitions*/ + /*--------------------------------------------------------*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + if(ioreq->irCount == DOCH_ACCESS_ALL_PARTITIONS) + sectorCountValue = 0xFF; + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_DISABLE_ACCESS; + in_regs.bSectorCount = sectorCountValue; + in_regs.bSectorNumber = (FLByte)(ioreq->irFlags); + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_SELECT_DEV(pdev->bAtaDevNum); + in_regs.bCommandStatus = DOCH_VSCMD_ACCESS_CONTROL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHDisablePartAccessSingleFloor(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d\r\n"), rc,pdev->bAtaDevNum)); + + return DOCH_GeneralFailure; + } +} + +DOCH_Error DOCHDisablePartAccess(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq ioreq2; + DOCH_Socket* pdev; + FLByte partNum = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*If partition resides ENTIRELY on Dev0*/ + /*=====================================*/ + if(DOCH_PARTITION_ON_DEV0) + { + rc = DOCHDisablePartAccessSingleFloor(ioreq); + return rc; + } + + /*If partition resides ENTIRELY on Dev1*/ + /*=====================================*/ + if(DOCH_PARTITION_ON_DEV1) + { + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + + if(pdev->sSpanData.bLastDev0PartSpanned) + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0 + 1)); + else + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0)); + + pdev->bAtaDevNum = 1; + rc = DOCHDisablePartAccessSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + return rc; + } + + /*If partition is spanned - collect both infos and combine*/ + /*========================================================*/ + if(DOCH_PARTITION_IS_SPANNED) + { + /*Set to chunk on Dev0*/ + /*--------------------*/ + rc = DOCHDisablePartAccessSingleFloor(ioreq); + if(rc != DOCH_OK) + return rc; + + /*Set to chunk on Dev0*/ + /*--------------------*/ + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.numOfSpannedPartitionOnDev0 + 1)); + + pdev->bAtaDevNum = 1; + rc = DOCHDisablePartAccessSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + if(rc != DOCH_OK) + return rc; + } + + return DOCH_OK; +} + +#if 0 + +/*----------------------------------------------------------------------*/ +/* D O C HS e n d H o s t P K e y */ +/* */ +/* Host sends its public key for this partition & random challenge */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irFlags : DOCH_ACCESS_USER_PASSWORD */ +/* DOCH_ACCESS_MASTER_PASSWORD */ +/* DOCH_ACCESS_GATE_KEEPER */ +/* irCount : Send key for the entire device */ +/* DOCH_ACCESS_ALL_PARTITIONS */ +/* irData : Pointer to DOCH_HostPublicKey structure */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_ACCESS_CONTROL */ +/* ATA sub-command: */ +/* DOCH_TX_HOST_PUBLICKEY */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHSendHostPublicKey(IOreq* ioreq) +{ + DOCH_Error rc; +#ifdef DOCH_BIG_ENDIAN + DOCH_HostPublicKey* hostPublicKeyToBig = (DOCH_HostPublicKey*)(ioreq->irData); +#endif /*DOCH_BIG_ENDIAN*/ + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + FLByte sectorCountValue = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check if Partition exceeds number of existing partitions*/ + /*--------------------------------------------------------*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + if(ioreq->irCount == DOCH_ACCESS_ALL_PARTITIONS) + sectorCountValue = 0xFF; + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_TX_HOST_PUBLICKEY; + in_regs.bSectorCount = sectorCountValue; + in_regs.bSectorNumber = (FLByte)(ioreq->irFlags); + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_LBA; + in_regs.bCommandStatus = DOCH_VSCMD_ACCESS_CONTROL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + ioreq->irData, + (sizeof(DOCH_HostPublicKey) / DOCH_SECTOR_SIZE)); + + #ifdef DOCH_BIG_ENDIAN + /*In case of a BIG ENDIAN host CPU, reorder bytes in 16 and 32 Bit variables*/ + hostPublicKeyToBig->wVersion = be_FLWord((FLByte*)&hostPublicKeyToBig->wVersion); + #endif /*DOCH_BIG_ENDIAN*/ + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHSendHostPublicKey(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* D O C HR e c e i v e D o c h P u b l i c K e y */ +/* */ +/* DOCH sends its public key, host's random challenge encrypted by DOCH */ +/* private key, and DOCH's random challenge to host */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irFlags : DOCH_ACCESS_USER_PASSWORD */ +/* DOCH_ACCESS_MASTER_PASSWORD */ +/* DOCH_ACCESS_GATE_KEEPER */ +/* irCount : Receive key for the entire device */ +/* DOCH_ACCESS_ALL_PARTITIONS */ +/* irData : Pointer to DOCH_DochPublicKey structure */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_ACCESS_CONTROL */ +/* ATA sub-command: */ +/* DOCH_RX_DOCH_PUBLICKEY */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHReceiveDochPublicKey(IOreq* ioreq) +{ + DOCH_Error rc; +#ifdef DOCH_BIG_ENDIAN + DOCH_DochPublicKey* dochPublicKeyToBig = (DOCH_DochPublicKey*)(ioreq->irData); +#endif /*DOCH_BIG_ENDIAN*/ + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + FLByte sectorCountValue = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check if Partition exceeds number of existing partitions*/ + /*--------------------------------------------------------*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + if(ioreq->irCount == DOCH_ACCESS_ALL_PARTITIONS) + sectorCountValue = 0xFF; + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_RX_DOCH_PUBLICKEY; + in_regs.bSectorCount = sectorCountValue; + in_regs.bSectorNumber = (FLByte)(ioreq->irFlags); + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_LBA; + in_regs.bCommandStatus = DOCH_VSCMD_ACCESS_CONTROL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + ioreq->irData, + (sizeof(DOCH_DochPublicKey) / DOCH_SECTOR_SIZE)); + + #ifdef DOCH_BIG_ENDIAN + /*In case of a BIG ENDIAN host CPU, reorder bytes in 16 and 32 Bit variables*/ + dochPublicKeyToBig->wVersion = be_FLWord((FLByte*)&dochPublicKeyToBig->wVersion); + #endif /*DOCH_BIG_ENDIAN*/ + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHReceiveDochPublicKey(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* D O C H V e r i f y H o s t K e y */ +/* */ +/* Host sends DOCH's random challenge encrypted by host's private key */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irFlags : DOCH_ACCESS_USER_PASSWORD */ +/* DOCH_ACCESS_MASTER_PASSWORD */ +/* DOCH_ACCESS_GATE_KEEPER */ +/* irCount : Verify key for the entire device */ +/* DOCH_ACCESS_ALL_PARTITIONS */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_ACCESS_CONTROL */ +/* ATA sub-command: */ +/* DOCH_VERIFY_HOST_KEY */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHVerifyHostKey(IOreq* ioreq) +{ + DOCH_Error rc; +#ifdef DOCH_BIG_ENDIAN + DOCH_VerifyHostKey* verifyHostKeyToBig = (DOCH_VerifyHostKey*)(ioreq->irData); +#endif /*DOCH_BIG_ENDIAN*/ + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + FLByte sectorCountValue = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check if Partition exceeds number of existing partitions*/ + /*--------------------------------------------------------*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + if(ioreq->irCount == DOCH_ACCESS_ALL_PARTITIONS) + sectorCountValue = 0xFF; + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_VERIFY_HOST_KEY; + in_regs.bSectorCount = sectorCountValue; + in_regs.bSectorNumber = (FLByte)(ioreq->irFlags); + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_LBA; + in_regs.bCommandStatus = DOCH_VSCMD_ACCESS_CONTROL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + ioreq->irData, + (sizeof(DOCH_VerifyHostKey) / DOCH_SECTOR_SIZE)); + + #ifdef DOCH_BIG_ENDIAN + /*In case of a BIG ENDIAN host CPU, reorder bytes in 16 and 32 Bit variables*/ + verifyHostKeyToBig->wVersion = be_FLWord((FLByte*)&verifyHostKeyToBig->wVersion); + #endif /*DOCH_BIG_ENDIAN*/ + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHVerifyHostKey(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else + return DOCH_GeneralFailure; + } +} + +#endif /*0*/ + +/*----------------------------------------------------------------------*/ +/* D O C H S e t P a r i t i o n P r o t e c t i o n */ +/* */ +/* Set partition properties (attributes/passkey) . */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Pointer to DOCH_PartitionProtectionAPI */ +/* irFlags : DOCH_PASSKEY_VALID */ +/* DOCH_ATTRIBUTES_VALID */ +/* DOCH_LOCK_AS_OTP */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_SET_PARTITION_PROTECTION */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHSetParitionProtectionSingleFloor(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_PartitionProtectionAPI* partProperties = (DOCH_PartitionProtectionAPI*)(ioreq->irData); + DOCH_Socket* pdev; + IOreq ioreq2; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check if Partition exceeds number of existing partitions*/ + /*--------------------------------------------------------*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + tffsset(&partFormatInfo, 0, sizeof(DOCH_PartitionFormatInfo)); + + /*Retrieve current partition info from DOCH*/ + /*-----------------------------------------*/ + tffsset(&ioreq2, 0, sizeof(IOreq)); + ioreq2.irHandle = ioreq->irHandle; + ioreq2.irData = &partitionInfoTemp; + rc = DOCHPartitionInfoSingleFloor(&ioreq2); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHSetParitionProtectionSingleFloor(): DOCHPartitionInfoSingleFloor Failed with status : "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d"), rc,pdev->bAtaDevNum)); + return rc; + } + + if((ioreq->irFlags & DOCH_ATTRIBUTES_VALID) == DOCH_ATTRIBUTES_VALID) + { + /*Format DOCH_PartitionProtectionAPI structure to DOCH_PartitionFormatInfo*/ + /*------------------------------------------------------------------------*/ + + DOCH_SetBits(&partFormatInfo.partitionAttributes2, + DOCH_PA2B_PROTECTION_TYPE, + DOCH_PA2O_PROTECTION_TYPE, + partProperties->dwProtectionType); + DOCH_SetBits(&partFormatInfo.partitionAttributes2, + DOCH_PA2B_USER_MODE, + DOCH_PA2O_USER_MODE, + partProperties->dwUserAccessMode); + DOCH_SetBits(&partFormatInfo.partitionAttributes2, + DOCH_PA2B_GUEST_MODE, + DOCH_PA2O_GUEST_MODE, + partProperties->dwGuestAccessMode); + DOCH_SetBits(&partFormatInfo.partitionAttributes2, + DOCH_PA2B_MASTER_CTRL, + DOCH_PA2O_MASTER_CTRL, + partProperties->dwMasterControl); + DOCH_SetBits(&partFormatInfo.partitionAttributes2, + DOCH_PA2B_ENCRYPT_TYPE, + DOCH_PA2O_ENCRYPT_TYPE, + partProperties->dwEncryptionType); + DOCH_SetBits(&partFormatInfo.partitionAttributes2, + DOCH_PA2B_LOCK_CTRL, + DOCH_PA2O_LOCK_CTRL, + partProperties->dwLockControl); + DOCH_SetBits(&partFormatInfo.partitionAttributes2, + DOCH_PA2B_MAX_AUTH_ATTEMPTS, + DOCH_PA2O_MAX_AUTH_ATTEMPTS, + partProperties->dwMaxNumOfAuthAttempts); + + /*Preserve current OTW setting (Can only be set by AddPartition)*/ + DOCH_SetBits(&partFormatInfo.partitionAttributes2, + DOCH_PA2B_OTP_BIT, + DOCH_PA2O_OTP_BIT, + ((partitionInfoTemp.partitionAttributes2 & DOCH_PA2B_OTP_BIT) >> DOCH_PA2O_OTP_BIT)); + + } + else + partFormatInfo.partitionAttributes2 = 0; + + if((ioreq->irFlags & DOCH_PASSKEY_VALID) == DOCH_PASSKEY_VALID) + tffscpy(&partFormatInfo.bPasskey[0], &partProperties->bPasskey[0], sizeof(partFormatInfo.bPasskey)); + else + tffsset(&partFormatInfo.bPasskey[0], 0, sizeof(partFormatInfo.bPasskey)); + + partFormatInfo.dwValidity = (ioreq->irFlags & (DOCH_PASSKEY_VALID | DOCH_ATTRIBUTES_VALID | DOCH_LOCK_AS_OTP +#ifdef FL_SOTP + |DOCH_SEQUENTIAL_OTP +#endif /*FL_SOTP*/ + )); + + #ifdef DOCH_BIG_ENDIAN + /*In case of a BIG ENDIAN host CPU, reorder bytes in 16 and 32 Bit variables*/ + partFormatInfo.dwValidity = be_FLDword((FLByte*)&partFormatInfo.dwValidity); + partFormatInfo.dwCommandFlagsOrStatuses = be_FLDword((FLByte*)&partFormatInfo.dwCommandFlagsOrStatuses); + partFormatInfo.partitionAttributes1 = be_FLDword((FLByte*)&partFormatInfo.partitionAttributes1); + partFormatInfo.partitionAttributes2 = be_FLDword((FLByte*)&partFormatInfo.partitionAttributes2); + partFormatInfo.nPartitionSize = be_FLDword((FLByte*)&partFormatInfo.nPartitionSize); + partFormatInfo.nFastAreaSize = be_FLDword((FLByte*)&partFormatInfo.nFastAreaSize); + + partFormatInfo.wFastAreaFactor = be_FLWord((FLByte*)&partFormatInfo.wFastAreaFactor); + #endif /*DOCH_BIG_ENDIAN*/ + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_SET_PARTITION_PROTECTION; + in_regs.bSectorCount = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_SELECT_DEV(pdev->bAtaDevNum); + in_regs.bCommandStatus = DOCH_VSCMD_PARTITION_MANAGEMENT; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + &partFormatInfo, + (sizeof(DOCH_PartitionFormatInfo) / DOCH_SECTOR_SIZE)); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHSetParitionProtectionSingleFloor(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d"), rc,pdev->bAtaDevNum)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else + return DOCH_GeneralFailure; + } +} + +DOCH_Error DOCHSetParitionProtection(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq ioreq2; + DOCH_Socket* pdev; + FLByte partNum = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*If partition resides ENTIRELY on Dev0*/ + /*=====================================*/ + if(DOCH_PARTITION_ON_DEV0) + { + rc = DOCHSetParitionProtectionSingleFloor(ioreq); + return rc; + } + + /*If partition resides ENTIRELY on Dev1*/ + /*=====================================*/ + if(DOCH_PARTITION_ON_DEV1) + { + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + + if(pdev->sSpanData.bLastDev0PartSpanned) + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0 + 1)); + else + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0)); + + pdev->bAtaDevNum = 1; + rc = DOCHSetParitionProtectionSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + return rc; + } + + /*If partition is spanned - collect both infos and combine*/ + /*========================================================*/ + if(DOCH_PARTITION_IS_SPANNED) + { + /*Set to chunk on Dev0*/ + /*--------------------*/ + rc = DOCHSetParitionProtectionSingleFloor(ioreq); + if(rc != DOCH_OK) + return rc; + + /*Set to chunk on Dev0*/ + /*--------------------*/ + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.numOfSpannedPartitionOnDev0 + 1)); + + pdev->bAtaDevNum = 1; + rc = DOCHSetParitionProtectionSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + if(rc != DOCH_OK) + return rc; + } + + return DOCH_OK; +} + +/*----------------------------------------------------------------------*/ +/* D O C H S e t P a r i t i o n U s e r A t t r i b u t e s */ +/* */ +/* Set partition user attributes . */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Pointer to DOCH_PartitionUserAttr */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_SET_PARTITION_USER_ATTR */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHSetParitionUserAttributesSingleFloor(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq ioreq2; +#ifdef DOCH_BIG_ENDIAN + DOCH_PartitionUserAttr* partAttrToBig = (DOCH_PartitionUserAttr*)(ioreq->irData); +#endif /*DOCH_BIG_ENDIAN*/ + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check if Partition exceeds number of existing partitions*/ + /*--------------------------------------------------------*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + /*First retrieve current attributes sector + (for protecting first 0x40 bytes that are SDK specific*/ + /*------------------------------------------------------*/ + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + ioreq2.irData = currentAttributes; + DOCHGetParitionUserAttributesSingleFloor(&ioreq2); + + /*Use currentAttributes bytes 0x41..0x200 to set requested*/ + /*--------------------------------------------------------*/ + tffscpy(¤tAttributes[DOCH_PART_INFO_SDK_RESERVED_BYTES], + (((FLByte*)ioreq->irData) + DOCH_PART_INFO_SDK_RESERVED_BYTES), + (DOCH_SECTOR_SIZE - DOCH_PART_INFO_SDK_RESERVED_BYTES)); + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_SET_PARTITION_USER_ATTR; + in_regs.bSectorCount = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_SELECT_DEV(pdev->bAtaDevNum); + in_regs.bCommandStatus = DOCH_VSCMD_PARTITION_MANAGEMENT; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + currentAttributes, + (sizeof(DOCH_PartitionUserAttr) / DOCH_SECTOR_SIZE)); + + #ifdef DOCH_BIG_ENDIAN + /*In case of a BIG ENDIAN host CPU, reorder bytes in 16 and 32 Bit variables*/ + #endif /*DOCH_BIG_ENDIAN*/ + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHSetParitionUserAttributesSingleFloor(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d\r\n"), rc, pdev->bAtaDevNum)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else + return DOCH_GeneralFailure; + } +} + +DOCH_Error DOCHSetParitionUserAttributes(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq ioreq2; + DOCH_Socket* pdev; + FLByte partNum = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Partition resides on Dev0*/ + /*-------------------------*/ + if((partNum <= pdev->sSpanData.bLastPartitionOnDev0) || + (!pdev->sSpanData.secondFloorActive)) + { + rc = DOCHSetParitionUserAttributesSingleFloor(ioreq); + if(rc != DOCH_OK) + return rc; + } + /*Partition resides on Dev1*/ + /*-------------------------*/ + else if(partNum <= pdev->wTotalNumOfPartitions) + { + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + + if(pdev->sSpanData.bLastDev0PartSpanned) + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0 + 1)); + else + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0)); + + pdev->bAtaDevNum = 1; + rc = DOCHSetParitionUserAttributesSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + if(rc != DOCH_OK) + return rc; + } + /*Partition not present*/ + /*---------------------*/ + else + return DOCH_PartitionNotFound; + + return DOCH_OK; +} + +/*----------------------------------------------------------------------*/ +/* D O C H G e t P a r i t i o n U s e r A t t r i b u t e s */ +/* */ +/* Get partition user attributes . */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Pointer to DOCH_PartitionUserAttr */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_GET_PARTITION_USER_ATTR */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHGetParitionUserAttributesSingleFloor(IOreq* ioreq) +{ + DOCH_Error rc; +#ifdef DOCH_BIG_ENDIAN + DOCH_PartitionUserAttr* partAttrToBig = (DOCH_PartitionUserAttr*)(ioreq->irData); +#endif /*DOCH_BIG_ENDIAN*/ + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check if Partition exceeds number of existing partitions*/ + /*--------------------------------------------------------*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_GET_PARTITION_USER_ATTR; + in_regs.bSectorCount = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = (pdev->bAtaDevNum * DOCH_DEVICE); + in_regs.bCommandStatus = DOCH_VSCMD_PARTITION_MANAGEMENT; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + ioreq->irData, + (sizeof(DOCH_PartitionUserAttr) / DOCH_SECTOR_SIZE)); + + #ifdef DOCH_BIG_ENDIAN + /*In case of a BIG ENDIAN host CPU, reorder bytes in 16 and 32 Bit variables*/ + #endif /*DOCH_BIG_ENDIAN*/ + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHGetParitionUserAttributesSingleFloor(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d\r\n"), rc, pdev->bAtaDevNum)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else + return DOCH_GeneralFailure; + } +} + +DOCH_Error DOCHGetParitionUserAttributes(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq ioreq2; + DOCH_Socket* pdev; + FLByte partNum = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Partition resides on Dev0*/ + /*-------------------------*/ + if((partNum <= pdev->sSpanData.bLastPartitionOnDev0) || + (!pdev->sSpanData.secondFloorActive)) + { + rc = DOCHGetParitionUserAttributesSingleFloor(ioreq); + } + /*Partition resides on Dev1*/ + /*-------------------------*/ + else if(partNum <= pdev->wTotalNumOfPartitions) + { + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + + if(pdev->sSpanData.bLastDev0PartSpanned) + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0 + 1)); + else + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0)); + + pdev->bAtaDevNum = 1; + rc = DOCHGetParitionUserAttributesSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + } + /*Partition not present*/ + /*---------------------*/ + else + return DOCH_PartitionNotFound; + + return rc; +} + +/*----------------------------------------------------------------------*/ +/* D O C H O p t i m i z e M e d i a */ +/* */ +/* Performs garbage collection. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* */ +/* irLength : DOCH_OPTIMIZE_BY_PREPARE_FOR_WRITE */ +/* based on information collected during previous */ +/* PREPARE FOR WRITE commands */ +/* DOCH_OPTIMIZE_DEFAULT */ +/* performs default optimization of the whole */ +/* partition or media */ +/* irFlags : DOCH_NORMAL_OPERATION */ +/* DOCH_IMMEDIATE_OPERATION */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_OPTIMIZE_MEDIA */ +/* */ +/* Returns: */ +/* irLength : Actual number of sectors available for writes */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHOptimizeMedia(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + FLByte action_type; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + if(ioreq->irFlags == DOCH_IMMEDIATE_OPERATION) + action_type = ERASE_IMMEDIATE; + else + action_type = ERASE_NORMAL; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_OPTIMIZE_MEDIA; + in_regs.bSectorCount = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + in_regs.bSectorNumber = (FLByte)(ioreq->irLength); + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = (action_type|DOCH_LBA); + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + /*Actual number of sectors available for writes*/ + ioreq->irSectorCount = out_regs.bSectorNumber + + ((FLSDword)out_regs.bCylLow << 8) + + ((FLSDword)out_regs.bCylHigh << 16) + + ((FLSDword)out_regs.bDriveHead << 24) ; + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHOptimizeMedia(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* D O C H G e t C u s t o m P a r a m e t e r */ +/* */ +/* Returns 16-bit custom DOCH parameter */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irCount : Parameter# (see DOCH_CustomParams) */ +/* irFlags : DOCH_CUSTOM_PARAM_DEFAULT - default value */ +/* DOCH_CUSTOM_PARAM_TEMP - current (saved) value*/ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_GET_CUSTOM_PARAM */ +/* */ +/* Returns: */ +/* irSectorNo : Custom parameter value (16-Bit) */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHGetCustomParameter(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + FLByte setType; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + if(ioreq->irFlags == DOCH_CUSTOM_PARAM_TEMP) + setType = CUSTOM_PARAM_TEMP; + else if(ioreq->irFlags == DOCH_CUSTOM_PARAM_DEFAULT) + setType = CUSTOM_PARAM_DEFAULT; + else + return DOCH_BadParameter; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_GET_CUSTOM_PARAM; + in_regs.bSectorCount = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = (FLByte)(ioreq->irCount & 0x00FF); + in_regs.bDriveHead = ((FLByte)(((ioreq->irCount & 0x0F00) >> 8)) | setType |DOCH_LBA); + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + /*Return retrieved custom parameter value*/ + /*---------------------------------------*/ + ioreq->irSectorNo = (out_regs.bCylLow << 8) + out_regs.bSectorNumber; + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHGetCustomParameter(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* D O C H S e t C u s t o m P a r a m e t e r */ +/* */ +/* Sets 16-bit custom DOCH parameter */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : Custom Parameter Number (DOCH_CustomParams) */ +/* irSectorNo : Custom Parameter Value (16-Bit) */ +/* irFlags : DOCH_CUSTOM_PARAM_DEFAULT - default value */ +/* DOCH_CUSTOM_PARAM_TEMP - current (saved) value*/ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_SET_CUSTOM_PARAM */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHSetCustomParameterSingleFloor(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + FLByte setType; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + if(ioreq->irFlags == DOCH_CUSTOM_PARAM_TEMP) + setType = CUSTOM_PARAM_TEMP; + else if(ioreq->irFlags == DOCH_CUSTOM_PARAM_DEFAULT) + setType = CUSTOM_PARAM_DEFAULT; + else + return DOCH_BadParameter; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_SET_CUSTOM_PARAM; + in_regs.bSectorCount = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + in_regs.bSectorNumber = (FLByte)(ioreq->irSectorNo & 0x00FF); + in_regs.bCylLow = (FLByte)((ioreq->irSectorNo & 0xFF00) >> 8); + in_regs.bCylHigh = (FLByte)(ioreq->irCount & 0x00FF); + in_regs.bDriveHead = (((FLByte)(((ioreq->irCount & 0x0F00) >> 8)) | setType) | DOCH_SELECT_DEV(pdev->bAtaDevNum)); + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHSetCustomParameterSingleFloor(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d\r\n"), rc, pdev->bAtaDevNum)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) /*Protection violation - IPL is write protected*/ + return DOCH_ProtectionFault; + else + return DOCH_GeneralFailure; + } +} + +DOCH_Error DOCHSetCustomParameter(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + DOCH_Socket* pdev; + FLByte origDevNum; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + origDevNum = pdev->bAtaDevNum; + + pdev->bAtaDevNum = 0; + rc = DOCHSetCustomParameterSingleFloor(ioreq); + if(rc != DOCH_OK) + return rc; + + if(pdev->wNumOfDevices > 1) + { + pdev->bAtaDevNum = 1; + rc = DOCHSetCustomParameterSingleFloor(ioreq); + pdev->bAtaDevNum = origDevNum; + } + + return rc; +} + +#if 0 +/*----------------------------------------------------------------------*/ +/* D O C H A u t o H a s h C o n t r o l */ +/* */ +/* Enable/Disable Auto Hash Read/Write */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : AUTO_HASH_ENABLE */ +/* AUTO_HASH_DISABLE */ +/* irLength : AUTO_HASH_READ */ +/* AUTO_HASH_WRITE */ +/* irFlags : DOCH_HASH_NO_ENCRYPTION */ +/* DOCH_HASH_ENCRYPT_BY_KEY */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_SECURITY_CTRL */ +/* ATA sub-command: */ +/* DOCH_AUTO_HASH_CONTROL */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHAutoHashControl(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_AUTO_HASH_CONTROL; + in_regs.bSectorCount = 0; + in_regs.bSectorNumber = (FLByte)((ioreq->irCount) | (ioreq->irLength<<1) | (ioreq->irFlags<<2)); + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_LBA; + in_regs.bCommandStatus = DOCH_VSCMD_EXT_SECURITY_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHAutoHashControl(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* D O C H R e a d C a l c u l a t e d H a s h */ +/* */ +/* Command for Paged partitions */ +/* Transfers to host digest(s) calculated from data on the flash. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_READ_CALCULATED_HASH */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHReadCalculatedHash(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = 0; + in_regs.bSectorCount = 0; + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_LBA; + in_regs.bCommandStatus = DOCH_VSCMD_READ_CALCULATED_HASH; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHReadCalculatedHash(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* D O C H W r i t e C a l c u l a t e d H a s h */ +/* */ +/* Command for Paged partitions */ +/* No data is transfered. Digest(s) calculated from data in the flash */ +/* are stored to the dedicated area on flash. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : DOCH_HASH_NO_ENCRYPTION */ +/* DOCH_HASH_ENCRYPT_BY_KEY */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_WRITE_CALCULATED_HASH */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHWriteCalculatedHash(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = 0; + in_regs.bSectorCount = 0; + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_LBA; + if(ioreq->irCount == DOCH_HASH_ENCRYPT_BY_KEY) + in_regs.bDriveHead |= HASH_BY_KEY; + else + in_regs.bDriveHead |= HASH_AS_IS; + in_regs.bCommandStatus = DOCH_VSCMD_WRITE_CALCULATED_HASH; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWriteCalculatedHash(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* D O C H R e a d O r i g i n a l H a s h */ +/* */ +/* Command for Paged partitions */ +/* Transfers to host digest(s) stored previously on dedicated area on */ +/* flash */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : DOCH_HASH_NO_ENCRYPTION */ +/* DOCH_HASH_ENCRYPT_BY_KEY */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_READ_ORIGINAL_HASH */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHReadOriginalHash(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Socket* pdev; + DOCH_Registers out_regs; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = 0; + in_regs.bSectorCount = 0; + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_LBA; + if(ioreq->irCount == DOCH_HASH_ENCRYPT_BY_KEY) + in_regs.bDriveHead |= HASH_BY_KEY; + else + in_regs.bDriveHead |= HASH_AS_IS; + in_regs.bCommandStatus = DOCH_VSCMD_READ_ORIGINAL_HASH; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHReadOriginalHash(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* D O C H W r i t e G i v e n H a s h */ +/* */ +/* Command for Paged partitions */ +/* Transfers from host digest(s) and stores them to the dedicated area */ +/* on flash */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : DOCH_HASH_NO_ENCRYPTION */ +/* DOCH_HASH_ENCRYPT_BY_KEY */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_WRITE_GIVEN_HASH */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHWriteGivenHash(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = 0; + in_regs.bSectorCount = 0; + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_LBA; + if(ioreq->irCount == DOCH_HASH_ENCRYPT_BY_KEY) + in_regs.bDriveHead = HASH_BY_KEY; + else + in_regs.bDriveHead = HASH_AS_IS; + in_regs.bCommandStatus = DOCH_VSCMD_WRITE_GIVEN_HASH; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWriteGivenHash(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* D O C H R e p o r t S u p p o r t e d A l g o r i t h m s */ +/* */ +/* Report supported algorithms */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irData : Pointer to DOCH_supportedAlgorithms structure */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_SECURITY_CTRL */ +/* ATA sub-command: */ +/* DOCH_REPORT_SUPPORTED_ALGORITHMS */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHReportSupportedAlgorithms(IOreq* ioreq) +{ + DOCH_Error rc; +#ifdef DOCH_BIG_ENDIAN + DOCH_supportedAlgorithms* suppAlgToBig = (DOCH_supportedAlgorithms*)(ioreq->irData); +#endif /*DOCH_BIG_ENDIAN*/ + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_REPORT_SUPPORTED_ALGORITHMS; + in_regs.bSectorCount = 0; + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_LBA; + in_regs.bCommandStatus = DOCH_VSCMD_EXT_SECURITY_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + ioreq->irData, + (sizeof(DOCH_supportedAlgorithms) / DOCH_SECTOR_SIZE)); + + #ifdef DOCH_BIG_ENDIAN + /*In case of a BIG ENDIAN host CPU, reorder bytes in 16 and 32 Bit variables*/ + suppAlgToBig->wVersion = be_FLWord((FLByte*)&suppAlgToBig->wVersion); + + suppAlgToBig->wSymmetricAlgorithmsSupported = be_FLDword((FLByte*)&suppAlgToBig->wSymmetricAlgorithmsSupported); + suppAlgToBig->wAsymmetricAlgorithmsSupported= be_FLDword((FLByte*)&suppAlgToBig->wAsymmetricAlgorithmsSupported); + suppAlgToBig->wHashSchemesSupported = be_FLDword((FLByte*)&suppAlgToBig->wHashSchemesSupported); + suppAlgToBig->wRNGSchemesSupported = be_FLDword((FLByte*)&suppAlgToBig->wRNGSchemesSupported); + suppAlgToBig->wDecompressionSchemesSupported= be_FLDword((FLByte*)&suppAlgToBig->wDecompressionSchemesSupported); + suppAlgToBig->wCompressionSchemesSupported = be_FLDword((FLByte*)&suppAlgToBig->wCompressionSchemesSupported); + #endif /*DOCH_BIG_ENDIAN*/ + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHReportSupportedAlgorithms(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* D O C H G e t A l g o r i t h m C a p a b i l i t i e s */ +/* */ +/* Get algorithms capabilities */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : Algorithm Category */ +/* irLength : Algorithm # in the Category */ +/* irData : Pointer to DOCH_AlgorithmCapabilities */ +/* structure */ +/* */ +/* */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_SECURITY_CTRL */ +/* ATA sub-command: */ +/* DOCH_GET_ALGORITHM_CAPABILITIES */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHGetAlgorithmCapabilities(IOreq* ioreq) +{ + DOCH_Error rc; +#ifdef DOCH_BIG_ENDIAN + DOCH_AlgorithmCapabilities* algCapToBig = (DOCH_AlgorithmCapabilities*)(ioreq->irData); +#endif /*DOCH_BIG_ENDIAN*/ + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_GET_ALGORITHM_CAPABILITIES; + in_regs.bSectorCount = (FLByte)(ioreq->irCount); + in_regs.bSectorNumber = (FLByte)(ioreq->irLength); + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_LBA; + in_regs.bCommandStatus = DOCH_VSCMD_EXT_SECURITY_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + ioreq->irData, + (sizeof(DOCH_AlgorithmCapabilities) / DOCH_SECTOR_SIZE)); + + #ifdef DOCH_BIG_ENDIAN + /*In case of a BIG ENDIAN host CPU, reorder bytes in 16 and 32 Bit variables*/ + algCapToBig->wVersion = be_FLWord((FLByte*)&algCapToBig->wVersion); + algCapToBig->wNumOfKeySizesSupported = be_FLWord((FLByte*)&algCapToBig->wNumOfKeySizesSupported); + algCapToBig->wNumOfModesSupported = be_FLWord((FLByte*)&algCapToBig->wNumOfModesSupported); + + algCapToBig->keysAttributes->dwSize + = be_FLDword((FLByte*)&algCapToBig->keysAttributes->dwSize); + algCapToBig->keysAttributes->dwCalcTime + = be_FLDword((FLByte*)&algCapToBig->keysAttributes->dwCalcTime); + algCapToBig->modesAttributes->wKeySizes + = be_FLWord((FLByte*)&algCapToBig->modesAttributes->wKeySizes); + #endif /*DOCH_BIG_ENDIAN*/ + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHGetAlgorithmCapabilities(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* D O C H S e t A l g o r i t h m M o d e */ +/* */ +/* Set algorithms mode */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : bits 0..7 - Algorithm Category */ +/* bits 8..15 - Algorithm # in category */ +/* bits 16..24 - Mode index */ +/* bits 24..31 - Key size index */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_SECURITY_CTRL */ +/* ATA sub-command: */ +/* DOCH_SET_ALGORITHM_MODE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHSetAlgorithmMode(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_SET_ALGORITHM_MODE; + in_regs.bSectorCount = (FLByte)(ioreq->irCount & 0x000F); + in_regs.bSectorNumber = (FLByte)((ioreq->irCount & 0x00F0) >> 8); + in_regs.bCylLow = (FLByte)((ioreq->irCount & 0x0F00) >> 16); + in_regs.bCylHigh = (FLByte)((ioreq->irCount & 0xF000) >> 24); + in_regs.bDriveHead = DOCH_LBA; + in_regs.bCommandStatus = DOCH_VSCMD_EXT_SECURITY_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHSetAlgorithmMode(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* D O C H S t a r t H a s h S t r e a m C a l c u l a t i o n */ +/* */ +/* Restart/Continue hash stream calculation */ +/* Several streams can be supported at the same time, but only one */ +/* should be active at any moment. */ +/* Host should issue Stop command to the current stream, before */ +/* starting or resuming a new stream. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : bits 0..7 - Algorithm Category (hash) */ +/* bits 8..15 - Algorithm # in category */ +/* bits 16..23 - Stream # */ +/* irLength : DOCH_HASH_REINITIALIZE */ +/* DOCH_HASH_CONTINUE */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_SECURITY_CTRL */ +/* ATA sub-command: */ +/* DOCH_START_HASH_STREAM_CALC */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHStartHashStreamCalculation(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_START_HASH_STREAM_CALC; + in_regs.bSectorCount = (FLByte)(ioreq->irCount & 0x000F); + in_regs.bSectorNumber = (FLByte)((ioreq->irCount & 0x00F0) >> 8); + in_regs.bCylLow = (FLByte)((ioreq->irCount & 0x0F00) >> 16); + in_regs.bCylHigh = 0; + in_regs.bDriveHead = ((FLByte)(ioreq->irLength))|DOCH_LBA; + in_regs.bCommandStatus = DOCH_VSCMD_EXT_SECURITY_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHStartHashStreamCalculation(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* D O C H R e a d S t o p H a s h S t r e a m C a l c */ +/* */ +/* Read/Stop hash stream calculation */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : DOCH_HASH_CONTINUE_ACCUM */ +/* DOCH_HASH_STOP_ACCUM */ +/* irLength : DOCH_HASH_DONT_RETURN_DATA */ +/* DOCH_HASH_RETURN_ACCUM_DIGEST */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_SECURITY_CTRL */ +/* ATA sub-command: */ +/* DOCH_READ_STOP_HASH_STREAM_CALC */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHReadStopHashStreamCalc(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_READ_STOP_HASH_STREAM_CALC; + in_regs.bSectorCount = 0; + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = ((FLByte)(ioreq->irCount) | (FLByte)(ioreq->irLength) |DOCH_LBA); + in_regs.bCommandStatus = DOCH_VSCMD_EXT_SECURITY_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHReadStopHashStreamCalc(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* D O C H R e t u r n R a n d om N u m b e r s */ +/* */ +/* Return random numbers */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : bits 0..7 - Algorithm Category */ +/* bits 8..15 - Algorithm # in category */ +/* irLength : # of 32-Bit random numbers to generate */ +/* (max is 64, e.g full sector) */ +/* irData : Pointer to 1 sector of data which will hold */ +/* the number of requested random numbers */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_SECURITY_CTRL */ +/* ATA sub-command: */ +/* DOCH_RETURN_RANDOM_NUMBERS */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHReturnRandomNumbers(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_RETURN_RANDOM_NUMBERS; + in_regs.bSectorCount = (FLByte)(ioreq->irCount & 0x000F); + in_regs.bSectorNumber = (FLByte)((ioreq->irCount & 0x00F0) >> 8); + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = ((FLByte)(ioreq->irLength))|DOCH_LBA; + in_regs.bCommandStatus = DOCH_VSCMD_EXT_SECURITY_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + ioreq->irData, + DOCH_SECTOR_SIZE); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHReturnRandomNumbers(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* D O C H S e t H a s h K e y */ +/* */ +/* Set hash key */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : DOCH_HASH_DECRYPTION_KEY */ +/* DOCH_HASH_ENCRYPTION_KEY */ +/* irLength : DOCH_HASH_USE_DOCH_PUBLIC_KEY */ +/* DOCH_HASH_USE_HOST_PUBLIC_KEY */ +/* DOCH_HASH_USE_PARTITION_PUBLIC_KEY */ +/* irFlags : DOCH_HASH_USE_DOCH_PRIVATE_KEY */ +/* DOCH_HASH_USE_HOST_PRIVATE_KEY */ +/* irData : 1 Sector of data in case of any "receive" */ +/* option. */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_SECURITY_CTRL */ +/* ATA sub-command: */ +/* DOCH_SET_KEYS */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHSetHashKey(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_SET_KEYS; + in_regs.bSectorCount = 0; + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + + in_regs.bDriveHead = ((FLByte)(ioreq->irCount) | + ((FLByte)(ioreq->irLength & 0x03) << 2) | + ((FLByte)(ioreq->irFlags & 0x03) << 4)) |DOCH_LBA; + + in_regs.bCommandStatus = DOCH_VSCMD_EXT_SECURITY_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHSetHashKey(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} + +#endif /*0*/ + + +/*----------------------------------------------------------------------*/ +/* f l D O C H G e t P o w e r M o d e */ +/* */ +/* Retrieve device power mode */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_SET_POWER_MODE */ +/* */ +/* Returns: */ +/* irFlags : */ +/* DOCH_PM_WORK_MODE */ +/* DOCH_PM_INACTIVE_MODE */ +/* irCount : */ +/* Bits 0..1 : Work Mode */ +/* DOCH_WM_NORMAL */ +/* DOCH_WM_LOW_FREQ */ +/* DOCH_WM_NORMAL_AND_AUTO_STBY */ +/* DOCH_WM_LOW_FREQ_AND_AUTO_STBY */ +/* Bits 4..5 : Inactive Mode */ +/* DOCH_IM_IDLE */ +/* DOCH_IM_DPD */ +/* DOCH_IM_IDLE_2_DPD */ +/* irLength : Value of timeout for automatic transfer to */ +/* Inactive mode (0 = disabled) */ +/* Timer value is in milliseconds. */ +/* If Inactive mode is "Standby to DPD" timer */ +/* resolution is 100 ms. */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHGetPowerMode(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_GET_POWER_MODE; + in_regs.bSectorCount = 0; + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead =DOCH_SELECT_DEV (pdev->bAtaDevNum); + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHGetPowerMode(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } + + /*Set output values*/ + ioreq->irFlags = out_regs.bSectorCount; + ioreq->irCount = out_regs.bSectorNumber; + ioreq->irLength = (out_regs.bCylLow + (out_regs.bCylHigh<<8)); + + return DOCH_OK; +} + +/*----------------------------------------------------------------------*/ +/* D O C H S e t P o w e r M o d e */ +/* */ +/* Set device power mode */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irFlags : */ +/* Bits 0..1 - which mode(s) should be set */ +/* DOCH_PM_SET_WORK_MODE */ +/* DOCH_PM_SET_INACTIVE_MODE */ +/* DOCH_PM_SET_BOTH_MODES */ +/* DOCH_PM_SET_NONE */ +/* Bit 2 - which mode device should pass to after set */ +/* DOCH_PM_WORK_MODE */ +/* DOCH_PM_INACTIVE_MODE */ +/* Bit 4 */ +/* DOCH_PM_SAVE_DEFAULT */ +/* (Save new settings as default settings ) */ +/* irCount : */ +/* Bits 0..1 : Work Mode to be set */ +/* DOCH_WM_NORMAL */ +/* DOCH_WM_LOW_FREQ */ +/* DOCH_WM_NORMAL_AND_AUTO_STBY */ +/* DOCH_WM_LOW_FREQ_AND_AUTO_STBY */ +/* Bits 4..5 : Inactive Mode to be set */ +/* DOCH_IM_IDLE */ +/* DOCH_IM_DPD */ +/* DOCH_IM_IDLE_2_DPD */ +/* irLength : Value of timeout for automatic transfer to */ +/* Inactive mode (0 = disabled) */ +/* Timer value is in milliseconds. */ +/* If Inactive mode is "Standby to DPD" timer */ +/* resolution is 100 ms. */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_SET_POWER_MODE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHSetPowerModeSingleFloor(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + FLByte setType; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + if((ioreq->irFlags & DOCH_PM_SAVE_DEFAULT) == DOCH_PM_SAVE_DEFAULT) + setType = DRIVE_HEAD_OPT1; + else + setType = 0; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_SET_POWER_MODE; + in_regs.bSectorCount = (FLByte)(ioreq->irFlags & 0x0000000F); + in_regs.bSectorNumber = (FLByte)ioreq->irCount; + in_regs.bCylLow = (FLByte)(ioreq->irLength & 0x000000FF); + in_regs.bCylHigh = (FLByte)((ioreq->irLength & 0x0000FF00) >> 8); + in_regs.bDriveHead = (DOCH_SELECT_DEV(pdev->bAtaDevNum) | setType); + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + if(rc == DOCH_OK) + { + /*Update DPD settings*/ + if( (ioreq->irFlags&DOCH_PM_SET_WORK_MODE) || (ioreq->irFlags&DOCH_PM_SET_BOTH_MODES) ) + { + gDpdSettings.activeMode = (ioreq->irCount & 0x0000000F); + } + if( (ioreq->irFlags&DOCH_PM_SET_INACTIVE_MODE) || (ioreq->irFlags&DOCH_PM_SET_BOTH_MODES) ) + { + gDpdSettings.inActiveMode = (ioreq->irCount & 0x000000F0); + } + + gDpdSettings.timeOut = ioreq->irLength; + + /*If HAL is SPI, disable DPD*/ + if(gAccessLayerType == DOCH_AL_SPI) + gDpdSettings.activeMode = DOCH_WM_NORMAL; + + return DOCH_OK; + } + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHSetPowerModeSingleFloor(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x deviceNum:\r\n"), rc,pdev->bAtaDevNum)); + + return DOCH_GeneralFailure; + } +} + +DOCH_Error DOCHSetPowerMode(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + pdev->bAtaDevNum = 0; + rc = DOCHSetPowerModeSingleFloor(ioreq); + if(rc != DOCH_OK) + return rc; + + if(pdev->wNumOfDevices > 1) + { + pdev->bAtaDevNum = 1; + rc = DOCHSetPowerModeSingleFloor(ioreq); + pdev->bAtaDevNum = 0; + } + + return rc; +} + +#if 0 /* save this api because the command defined in spec */ +/*----------------------------------------------------------------------*/ +/* D O C H C a l i b r a t e C l o c k */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : Desired SYS ICMU clock, in MHZ */ +/* irLength : Desired FLASH ICMU clock, in MHZ */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_CALIBRATE_CLOCK */ +/* */ +/* Returns: */ +/* irCount : SYS ICMU correction factor */ +/* irLength : FLASH ICMU correction factor */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHCalibrateClock(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_CALIBRATE_CLOCK; + in_regs.bSectorCount = (FLByte)ioreq->irCount; + in_regs.bSectorNumber = 0; + in_regs.bCylLow = (FLByte)ioreq->irLength; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_LBA; + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + /*Output*/ + /*------*/ + ioreq->irCount = out_regs.bSectorCount + (out_regs.bSectorNumber << 8); + ioreq->irLength= out_regs.bCylLow + (out_regs.bCylHigh << 8); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHCalibrateClock(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} +#endif /*0*/ /* save this api because the command defined in spec */ + +/******************************************************************************/ +/* + * General (Control/Configuration) + */ +/******************************************************************************/ + +void setConfigHWDefaults(void) +{ + gConfigHWDefaults[DOCH_BURST_WRITE_MODE_CTRL] = DOCH_BURST_WRITE_MODE_DEFAULT; + + gConfigHWDefaults[DOCH_BURST_READ_MODE_CTRL] = DOCH_BURST_READ_MODE_DEFAULT; + + gConfigHWDefaults[DOCH_IPL_CTRL] = DOCH_IPL_CTRL_DEFAULT; + + gConfigHWDefaults[DOCH_WARM_BOOT_CTRL] = DOCH_WARM_BOOT_CTRL_DEFAULT; + + gConfigHWDefaults[DOCH_POWER_DOWN] = DOCH_POWER_DOWN_DEFAULT; + + gConfigHWDefaults[DOCH_DMA_CTRL] = DOCH_DMA_CTRL_DEFAULT; + + gConfigHWDefaults[DOCH_DMA_NEGATION_CTRL] = DOCH_DMA_NEGATION_CTRL_DEFAULT; + + gConfigHWDefaults[DOCH_SLOCK] = DOCH_SLOCK_DEFAULT; + + gConfigHWDefaults[DOCH_ENDIAN_CTRL] = DOCH_ENDIAN_CTRL_DEFAULT; + + gConfigHWDefaults[DOCH_OPERATION_MODE_CTRL] = DOCH_OPERATION_MODE_CTRL_DEFAULT; + + gConfigHWInitDone = DOCH_GLOBAL_BOOL_PATTERN; +} + +/*----------------------------------------------------------------------*/ +/* D O C H H w C o n f i g */ +/* */ +/* Control HW registers */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irFlags : HW Configuration type */ +/* (See DOCH_HwConfigType for values) */ +/* irLength : HW configuration type dependant */ +/* */ +/* ATA command: */ +/* NONE */ +/* ATA sub-command: */ +/* NONE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHConfigHW(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq ioreq2; + FLByte devNum = 0; + DOCH_Socket* pdev; + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + if(pdev == NULL) + return DOCH_DiskNotFound; + + /* Set default values if not set yet (e.g. DochSDKInit() was not called yet!) */ + if(gConfigHWInitDone != DOCH_GLOBAL_BOOL_PATTERN) + setConfigHWDefaults(); + + gConfigHWDefaults[ioreq->irFlags] = ioreq->irLength; + + /*If init was not done yet, only keep requested value*/ + if(gSdkDOCAddressObtained != DOCH_GLOBAL_BOOL_PATTERN) + { + return DOCH_OK; + } + +setConfigItemToDevice: + + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, DOCH_SELECT_DEV(devNum)); + DOCH_DELAY_AFTER_DEVICE_SWITCH(pdev,devNum); + + + switch((DOCH_HwConfigType)(ioreq->irFlags)) + { + case DOCH_BURST_WRITE_MODE_CTRL: + rc = doch_setConfigReg16 (pdev, + HIB_BURST_WRITE_MODE_CTRL_REG, + ioreq->irLength); + break; + + case DOCH_BURST_READ_MODE_CTRL: + rc = doch_setConfigReg16 (pdev, + HIB_BURST_READ_MODE_CTRL_REG, + ioreq->irLength); + break; + + case DOCH_IPL_CTRL: + if(ioreq->irLength & DOCH_IPL_WRITE_ENABLE) + { + FLWord wTmpConfigVal = doch_getConfigReg16(pdev, HIB_IPL_CONTROL_REG); + if((wTmpConfigVal & DOCH_IPL_WRITE_READY) != DOCH_IPL_WRITE_READY) + { + rc = DOCH_ATANotReady; + break; + } + } + rc = doch_setConfigReg16 (pdev, + HIB_IPL_CONTROL_REG, + ioreq->irLength); + break; + + case DOCH_WARM_BOOT_CTRL: + rc = doch_setConfigReg16 (pdev, + HIB_WARM_BOOT_REG, + ioreq->irLength); + break; + + case DOCH_POWER_DOWN: + rc = doch_setConfigReg16 (pdev, + HIB_POWER_DOWN_REG, + ioreq->irLength); + break; + + case DOCH_DMA_CTRL: + rc = doch_setConfigReg16 (pdev, + HIB_DMA_CTRL_REG, + ioreq->irLength); + break; + + case DOCH_DMA_ENABLE: + if(ioreq->irLength) + { +#ifdef DOCH_DMA_CONFIG + gIsDMAEnabled = DOCH_GLOBAL_BOOL_PATTERN; +#endif /*DOCH_DMA_CONFIG*/ + } + else + { + gIsDMAEnabled = 0; + } + break; + + case DOCH_DMA_NEGATION_CTRL: + rc = doch_setConfigReg16 (pdev, + HIB_DMA_NEGATION_REG, + ioreq->irLength); + break; + + case DOCH_SLOCK: + rc = doch_setConfigReg16(pdev, + HIB_SW_LOCK_REG, + ioreq->irLength); + if(rc != DOCH_OK) + break; + + /* If SLOCK was requested, set by ATA command also*/ + if(ioreq->irLength == TRUE) + { + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irCount = DOCH_CP_SLOCK_CTRL; + ioreq2.irSectorNo = ioreq->irLength; + ioreq2.irFlags = DOCH_CUSTOM_PARAM_TEMP; + rc = DOCHSetCustomParameter(&ioreq2); + if(rc != DOCH_OK) + break; + } + break; + + case DOCH_ENDIAN_CTRL: + rc = doch_setConfigReg16(pdev, + HIB_ENDIAN_CTRL_REG, + ioreq->irLength); + break; + + case DOCH_OPERATION_MODE_CTRL: + rc = doch_setConfigReg16(pdev, + HIB_OPERATION_MODE_REG, + ioreq->irLength); + break; + + case DOCH_POWER_MODE_CTRL: + rc = doch_setConfigReg16(pdev, + HIB_POWER_MODE_REG, + ioreq->irLength); + break; + + default: + return DOCH_FeatureNotSupported; + } + + /* If Dev1 exists, set config Item as well*/ + if ((devNum == 0) && (ATA_MAX_NUM_OF_DEVICES>1)) + { + devNum = 1; + goto setConfigItemToDevice; + } + + if (devNum == 1) + { + /*Set device back to Dev0*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, DOCH_SELECT_DEV0); + DOCH_DELAY_AFTER_DEVICE_SWITCH(pdev,0); + } + + return rc; +} + +/*----------------------------------------------------------------------*/ +/* D O C H R e c o v e r F r o m P o w e r L o s s */ +/* */ +/* Set last known values of DOCH control registers back to device after */ +/* power loss was detected. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irFLags : DOCH_DO_NOT_REINIT_MASTER */ +/* */ +/* ATA command: */ +/* NONE */ +/* ATA sub-command: */ +/* NONE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHRecoverFromPowerLoss(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + DOCH_Socket* pdev; + register FLByte i; + IOreq ioreq2; + FLByte bConfFloor = FALSE; + FLByte bFloorsNum; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*general initializations (not required if master was already configured)*/ + if (!(ioreq->irFlags & DOCH_DO_NOT_REINIT_MASTER)) + { + /* Re-set all control register values to device */ + rc = doch_configCommon(pdev); + if(rc != DOCH_OK) + return rc; + bConfFloor =TRUE; + } + + /* init both floors */ + rc = doch_init_floors(pdev,bConfFloor,&bFloorsNum); + if(rc != DOCH_OK) + return rc; + + for (i=0;iwNumOfDevices;i++) + { + pdev->bAtaDevNum = i; + + /*Restore DPD settings */ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irHandle = ioreq->irHandle; + ioreq2.irFlags = (DOCH_PM_SET_BOTH_MODES | DOCH_PM_WORK_MODE); + ioreq2.irCount = (gDpdSettings.activeMode | gDpdSettings.inActiveMode); + ioreq2.irLength = gDpdSettings.timeOut; + rc = DOCHSetPowerModeSingleFloor(&ioreq2); + if(rc != DOCH_OK) + return rc; + + /*Restore transfer mode */ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irHandle =ioreq->irHandle; + ioreq2.irCount = pdev->device[i].dataTransferMode; + ioreq2.irLength = pdev->device[i].dwMulti_Current; + rc = DOCHSetDataTransferModeSingleFloor(&ioreq2); + if(rc != DOCH_OK) + return rc; + +#ifdef FL_REPORT_INTERNAL_ERRORS + /* Set DocH to report internal errors*/ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irCount = DOCH_CP_REPORT_ECC_MODE; + ioreq2.irSectorNo = (FLWord)(DOCH_ENABLE_REPORT_ECC_ERRORS); + ioreq2.irFlags = DOCH_CUSTOM_PARAM_TEMP; + ioreq2.irHandle =ioreq->irHandle; + rc = DOCHSetCustomParameterSingleFloor(&ioreq2); + if(rc != DOCH_OK) + { + DBG_PRINT_WRN_PRM(FLZONE_ATA, (FLTXT("\r\nWARNING: Failed setting mDoc to report internal errors with status %d \r\n"), rc)); + rc=DOCH_OK; + /*return rc;*/ /*do not fail - backward compatibility*/ + } +#endif /*FL_REPORT_INTERNAL_ERRORS*/ + + } /*for each floor*/ + + pdev->bAtaDevNum =0; +#ifdef CHECK_POWER_ON_EVERY_COMMAND + { + IOreq ioreq2; + + /*Make sure next calls to DOCHGetResetStatus() will reflect actual reset*/ + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + DOCHGetResetStatus(&ioreq2); + } +#endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + + return rc; +} + +/*----------------------------------------------------------------------*/ +/* f l D O C H A t a R e s e t */ +/* */ +/* Perform ATA reset operation for a specific socket */ +/* Effects both Device0 and Device1 */ +/* */ +/* Parameters: */ +/* socketNum : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* NONE */ +/* ATA sub-command: */ +/* NONE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error flDOCHAtaReset(FLByte socketNum) +{ + DOCH_Error rc; + IOreq ioreq; + DOCH_Socket* pdev; + DOCH_InitSocket initSocket; + + DOCH_get_socket(pdev, socketNum); + + DBG_PRINT_ERR(FLZONE_API, "\r\n***********************************\r\n"); + DBG_PRINT_ERR(FLZONE_API, "\r\n* Performing flDOCHAtaReset() !!! *\r\n"); + DBG_PRINT_ERR(FLZONE_API, "\r\n***********************************\r\n"); + + /*Protect against access time set to 0*/ + if(gDochAccessNanosec == 0) + return DOCH_BadParameter; + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + + /*----------------------------------------------------------*/ + /* Reset the device(s) using "Set alert level" command */ + /* In case of cascaded configuration - both devices are */ + /* reset prior to checking status since in case of changing */ + /* window size (8/128KB) - Dev1 will not be reachable after */ + /* resetting Dev0 and reinitializing the SDK window */ + /*----------------------------------------------------------*/ + /*Send reset command to Dev1 (if exists)*/ + if(pdev->wNumOfDevices > 1) + { + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, DOCH_SELECT_DEV1); /*Dev1*/ + DOCH_DELAY_AFTER_DEVICE_SWITCH(pdev,1); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_FEATURES_REG, 0x7F); /*Set Alert Level*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_CNT_REG, 1); /*"And Reboot"*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_NO_REG, 0xFF); /*Invalid alert level*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_COMMAND_REG, 0xFC); /*Extended Device Contrl*/ + } + /*Send reset command to Dev0*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, DOCH_SELECT_DEV0); /*Dev0*/ + DOCH_DELAY_AFTER_DEVICE_SWITCH(pdev,0); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_FEATURES_REG, 0x7F); /*Set Alert Level*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_CNT_REG, 1); /*"And Reboot"*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_NO_REG, 0xFF); /*Invalid alert level*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_COMMAND_REG, 0xFC); /*Extended Device Contrl*/ + +#ifdef DEBUG_TIMEOUT + { + FLDword dwTimeAfterHigh,dwTimeAfterLow,dwTimeBeforeHigh,dwTimeBeforeLow; + FLDword diffHigh,diffLow,dwWaitingTime; + FLDword scaledFreq; + + GetInternalSysTimer(&dwTimeBeforeHigh,&dwTimeBeforeLow); +#endif /*DEBUG_TIMEOUT*/ + + DOCH_DELAY_MSEC(200); + +#ifdef DEBUG_TIMEOUT + GetInternalSysTimer(&dwTimeAfterHigh,&dwTimeAfterLow); + scaledFreq= SysTimerFrequency/1000; /*mSec*/ + diffHigh=(dwTimeAfterHigh-dwTimeBeforeHigh); + if(dwTimeAfterLow>=dwTimeBeforeLow) + { + diffLow= dwTimeAfterLow-dwTimeBeforeLow; + } + else + { + if (!diffHigh) + { + DBG_PRINT_ERR(FLZONE_ATA,"\nticks difference is negative\n"); + } + diffLow= 0xFFFFFFFFl- dwTimeBeforeLow + dwTimeAfterLow; + diffHigh --; + + } + dwWaitingTime = (FLSDword)( (((0xFFFFFFFFl)/(scaledFreq)))*(diffHigh))+ + (((0xFFFFFFFFl)%(scaledFreq))*(diffHigh+1) + (diffLow))/(scaledFreq); + + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("\nTicks when started:high %lu low %lu"),dwTimeBeforeHigh,dwTimeBeforeLow)); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("\nTicks when timeout:high %lu low %lu"),dwTimeAfterHigh,dwTimeAfterLow)); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("\nTicks diff: high %d low %d"),diffHigh,diffLow)); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("\nDetected frequency %lu"), SysTimerFrequency)); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("\nDelay time %d msec"), dwWaitingTime)); + + } +#endif /*DEBUG_TIMEOUT*/ + + /* Search for the current window*/ + initSocket.nDeviceAddress = pdev->dwPhysicalAddress; + rc=doch_init_window (socketNum, initSocket); + if(rc != DOCH_OK) + return rc; + + tffsset(&ioreq, 0, sizeof(ioreq)); + DOCH_SET_SOCKET_TO_IOREQ_HANDLE(&ioreq, socketNum); + ioreq.irFlags= DOCH_DO_NOT_REINIT_MASTER; /* master was initialized in init_window*/ + rc = DOCHRecoverFromPowerLoss(&ioreq); + + return rc; +} + +/*----------------------------------------------------------------------*/ +/* f l D O C H S e t E n v V a r */ +/* */ +/* Set environment variable. */ +/* Available environment variables are listed in DOCH_EnVars. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based, if relevant) */ +/* irFlags : Environment variable */ +/* */ +/* irLength : Value to set */ +/* */ +/* ATA command: */ +/* NONE */ +/* ATA sub-command: */ +/* NONE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error flDOCHSetEnvVar(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq ioreq2; + + switch((DOCH_EnVars)(ioreq->irFlags)) + { +#ifdef FL_VERIFY_WRITE + case DOCH_ENV_VERIFY_WRITE: + if(ioreq->irLength != 0) + gDochVerifyWrite[DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)] = DOCH_GLOBAL_BOOL_PATTERN; + else + gDochVerifyWrite[DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)] = 0; + return DOCH_OK; +#endif /*FL_VERIFY_WRITE*/ + +#ifdef FL_UTILS_QUICK_INIT + case DOCH_ENV_QUICK_INIT: + /*Seek for 1 device only*/ + if (ioreq->irLength != 0) + gDochQuickInit = DOCH_GLOBAL_BOOL_PATTERN; + else /*Seek for all devices*/ + gDochQuickInit = 0; +#endif /*FL_UTILS_QUICK_INIT*/ + + case DOCH_ENV_ATA_DEBUG: + if(ioreq->irLength != 0) + gDochAtaDebug = DOCH_GLOBAL_BOOL_PATTERN; + else + gDochAtaDebug = 0; + return DOCH_OK; + + case DOCH_ENV_BLOCK_SPI: + if(gSdkInitDone != DOCH_GLOBAL_BOOL_PATTERN) + { + /* We do not have a window address yet - can be added in the future. */ + DBG_PRINT_ERR(FLZONE_API, "Can not set SPI BLOCKING mode before calling init routine.\r\n"); + return DOCH_ATANotReady; + } + /* Take mutex for current device */ + rc = dochSetMutex(DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + DOCH_ON, + DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "bdCallDOCH(): dochSetMutex failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + return rc; + } + + /* SDK is already initialized */ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irCount = DOCH_CP_WORK_MODES; + ioreq2.irFlags = DOCH_CUSTOM_PARAM_TEMP; + + /*Retreive current value (retrieved in irSectorNo)*/ + rc = DOCHGetCustomParameter(&ioreq2); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "flDOCHSetEnvVar(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + } + else + { + /*Modify value*/ + if(ioreq->irLength != 0) + { + ioreq2.irSectorNo |= DOCH_WORK_MODES_BLOCK_SPI; + } + else + { + ioreq2.irSectorNo &= ~(DOCH_WORK_MODES_BLOCK_SPI); + } + + /*Set modified value*/ + + rc = DOCHSetCustomParameter(&ioreq2); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "flDOCHSetEnvVar(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + } + } + /* Free mutex for current device */ + dochSetMutex(DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + DOCH_OFF, + DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq)); + + return rc; + + case DOCH_ENV_NO_ATA_TIMEOUT: + if(ioreq->irLength != 0) + { + gATANoTimeout = DOCH_GLOBAL_BOOL_PATTERN; + } + else + { + gATANoTimeout = 0; + } + + return DOCH_OK; + + case DOCH_ENV_AUTO_DPD_BY_HOST: + if(ioreq->irLength != 0) + gAutoDPDByHost = DOCH_GLOBAL_BOOL_PATTERN; + else + gAutoDPDByHost = 0; + + return DOCH_OK; + + default: + break; + } + + return DOCH_FeatureNotSupported; +} + +/*----------------------------------------------------------------------*/ +/* D O C H _ C l e a n I R Q _ I n t e r r u p t */ +/* */ +/* Clear the ATA interrupt. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* NONE */ +/* ATA sub-command: */ +/* NONE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHClearIRQ(IOreq* ioreq) +{ + DOCH_Error rc = clearATAInterrupt(DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + return rc; +} + +/*----------------------------------------------------------------------*/ +/* f l D O C H G e t P h y s i c a l A d d r e s s */ +/* */ +/* Retrieve physical address of the socket. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* NONE */ +/* ATA sub-command: */ +/* NONE */ +/* */ +/* Returns: */ +/* irCount : Socket Physical Address */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHGetPhysicalAddress(IOreq* ioreq) +{ + DOCH_Socket* pdev; + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + ioreq->irCount = pdev->dwPhysicalAddress; + + return DOCH_OK; +} + +#ifdef FL_SLPP +/*----------------------------------------------------------------------*/ +/* f l D O C H S L P P U n l o c k R a n g e */ +/* */ +/* Unlock a range of sectors on a sector protected partition. */ +/* */ +/* Parameters: */ +/* irHandle : bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irCount : First sector to unlock */ +/* irLength : Number of sectors to unlock */ +/* irData : Pointer to an 8 bytes passkey array */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_ACCESS_CONTROL */ +/* ATA sub-command: */ +/* DOCH_SLPP_UNLOCK_RANGE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHSLPPUnlockRange(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + DOCH_SLPPRangeRequestSector rangeReq; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + tffsset(&rangeReq, 0, sizeof(rangeReq)); + rangeReq.dwRangeStartSector = ioreq->irCount; + rangeReq.dwRangeSizeInSectors = ioreq->irLength; + tffscpy(&rangeReq.passkey, ioreq->irData, 8); + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_SLPP_UNLOCK_RANGE; + in_regs.bSectorCount = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_LBA; + in_regs.bCommandStatus = DOCH_VSCMD_ACCESS_CONTROL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + &rangeReq, + 1); + + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHSLPPUnlockRange(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* f l D O C H S L P P U n l o c k E n t i r e P a r t i t i o n */ +/* */ +/* Unlock an entire Sector Protected Partition. */ +/* */ +/* Parameters: */ +/* irHandle : bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irData : Pointer to an 8 bytes passkey array */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_ACCESS_CONTROL */ +/* ATA sub-command: */ +/* DOCH_SLPP_UNLOCK_ENTIRE_PARTITION */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHSLPPUnlockEntirePartition(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + DOCH_SLPPRangeRequestSector rangeReq; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + tffsset(&rangeReq, 0, sizeof(rangeReq)); + tffscpy(&rangeReq.passkey, ioreq->irData, 8); + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_SLPP_UNLOCK_ENTIRE_PARTITION; + in_regs.bSectorCount = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_LBA; + in_regs.bCommandStatus = DOCH_VSCMD_ACCESS_CONTROL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + &rangeReq, + 1); + + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHSLPPUnlockEntirePartition(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* f l D O C H S L P P L o c k R a n g e */ +/* */ +/* Lock a range of sectors on a sector protected partition. */ +/* */ +/* Parameters: */ +/* irHandle : bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irCount : First sector to lock */ +/* irLength : Number of sectors to lock */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_ACCESS_CONTROL */ +/* ATA sub-command: */ +/* DOCH_SLPP_LOCK_RANGE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHSLPPLockRange(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + DOCH_SLPPRangeRequestSector rangeReq; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + tffsset(&rangeReq, 0, sizeof(rangeReq)); + rangeReq.dwRangeStartSector = ioreq->irCount; + rangeReq.dwRangeSizeInSectors = ioreq->irLength; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_SLPP_LOCK_RANGE; + in_regs.bSectorCount = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_LBA; + in_regs.bCommandStatus = DOCH_VSCMD_ACCESS_CONTROL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + &rangeReq, + 1); + + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHSLPPLockRange(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* f l D O C H S L P P S t i c k y L o c k R a n g e */ +/* */ +/* Applies sticky lock to a range of sectors on a sector protected */ +/* partition. */ +/* */ +/* Parameters: */ +/* irHandle : bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irCount : First sector to sticky lock */ +/* irLength : Number of sectors to sticky lock */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_ACCESS_CONTROL */ +/* ATA sub-command: */ +/* DOCH_SLPP_STICKY_LOCK_RANGE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHSLPPStickyLockRange(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + DOCH_SLPPRangeRequestSector rangeReq; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + tffsset(&rangeReq, 0, sizeof(rangeReq)); + rangeReq.dwRangeStartSector = ioreq->irCount; + rangeReq.dwRangeSizeInSectors = ioreq->irLength; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_SLPP_STICKY_LOCK_RANGE; + in_regs.bSectorCount = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_LBA; + in_regs.bCommandStatus = DOCH_VSCMD_ACCESS_CONTROL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + &rangeReq, + 1); + + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHSLPPStickyLockRange(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* f l D O C H S L P P R e p o r t R a n g e s */ +/* */ +/* Reports unlocked and sticky locked ranges of sector protected */ +/* partition. */ +/* */ +/* Parameters: */ +/* irHandle : bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irData : Pointer to DOCH_SLPPReport structure */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_ACCESS_CONTROL */ +/* ATA sub-command: */ +/* DOCH_SLPP_REPORT_LOCKED_RANGES */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHSLPPReportLockedRanges(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_SLPP_REPORT_LOCKED_RANGES; + in_regs.bSectorCount = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_LBA; + in_regs.bCommandStatus = DOCH_VSCMD_ACCESS_CONTROL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + ioreq->irData, + 1); + + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHSLPPReportLockedRanges(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else + return DOCH_GeneralFailure; + } +} +#endif /*FL_SLPP*/ +/******************************************************************************/ +/* + * Pass-through routine + */ +/******************************************************************************/ + +/*----------------------------------------------------------------------*/ +/* D O C H A t a P a s s T h r o u g h */ +/* */ +/* Parameters: */ +/* socketNum : Socket to perform operation on */ +/* passThruOP : "0" - No Data */ +/* "1" - Data IN */ +/* "2" - Data OUT */ +/* in_regs : ATA Input registers values */ +/* out_regs : ATA Output registers values */ +/* secNum : Number of sectors to perform */ +/* userBuff : Pointer to user buffer */ +/* (for data in/out commands) */ +/* useInterrupt : Use interrupt when waiting on ATA busy */ +/* */ +/* ATA command: */ +/* user defined (in_regs->bCommandStatus) */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHAtaPassThrough(FLSNative socketNum, + FLSNative passThruOP, + DOCH_Registers *in_regs, + DOCH_Registers *out_regs, + FLNative secNum, + void* userBuff, + FLBoolean useInterrupt) +{ + DOCH_Error rc; + DOCH_PassThru_Op ptOP = (DOCH_PassThru_Op)passThruOP; + FLSNative devNum = ((in_regs->bDriveHead & DOCH_DEVICE) == DOCH_DEVICE); + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, socketNum); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Enable interrupts*/ + /*-----------------*/ + pdev->bUseInterrupt = useInterrupt; + + + /*Perform ATA command with registers values set above*/ + /*---------------------------------------------------*/ + rc = doch_ata_passthru (socketNum, devNum, ptOP, in_regs, out_regs, userBuff, secNum); + + /*Disable interrupts*/ + /*------------------*/ + pdev->bUseInterrupt = FALSE; + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHAtaPassThrough(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return rc; + } + +} + +/*----------------------------------------------------------------------*/ +/* D o c h S D K I n i t */ +/* */ +/* Initializes the DOCH system, sockets and timers. */ +/* */ +/* Parameters: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ + +DOCH_Error DochSDKInit(void) +{ + DOCH_Error rc = DOCH_OK; + IOreq ioreq; + IOreq ioreq2; + + /*Set global variable values*/ +#ifdef FL_VERIFY_WRITE + tffsset(gDochVerifyWrite, 0, sizeof(gDochVerifyWrite)); +#endif /*FL_VERIFY_WRITE*/ + tffsset(gDochIrqEnabled, 0, sizeof(gDochIrqEnabled)); + gAccessLayerType = DOCH_AL_NONE; + gATANoTimeout = 0; + gAutoDPDByHost = 0; + gDochAccessNanosec = DOCH_ACCESS_NANOSEC; + + /*Protect against access time set to 0*/ + if(gDochAccessNanosec == 0) + return DOCH_BadParameter; + + /*Set DPD settings to defaults*/ + gDpdSettings.activeMode = DOCH_DPD_DEFAULT_ACTIVE_MODE; + gDpdSettings.inActiveMode = DOCH_DPD_DEFAULT_INACTIVE_MODE; + gDpdSettings.timeOut = DOCH_DPD_DEFAULT_DPD_TIMEOUT; + + /* Set ConfigHW items to defaults */ + if(gConfigHWInitDone != DOCH_GLOBAL_BOOL_PATTERN) + setConfigHWDefaults(); + +#ifdef DOCH_DMA_CONFIG + /* DMA channel was not opened yet... */ + gDMAChannelOpen = 0; +#endif /*DOCH_DMA_CONFIG*/ + + /* Init system related */ + DOCH_SYS_FUNC_INIT; + + /* Register DOCH components */ + rc = (DOCH_Error)flRegisterDochParams(); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "flRegisterDochParams(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + return rc; + } + + +#ifndef DOCH_NO_AUTO_WIPE_SECTORS + /* If Device User Attributes indicate that a secure wipe operation to Dev1 + was not issued (due to power failure) - complete the task before init is declared + as done */ + + /*Retrieve device user attributes*/ + tffsset(&ioreq, 0, sizeof(ioreq)); + DOCH_SET_SOCKET_TO_IOREQ_HANDLE(&ioreq, 0); + ioreq.irData = &devUserAttr; + DOCHGetDiskUserAttributes(&ioreq); + if(devUserAttr.sdkAttributes.sSecureDeleteDev1.bOperationRequired) + { + DBG_PRINT_ERR(FLZONE_API, "DochSDKInit(): Completing wipe-sectors operation due to power failure...\r\n"); + + tffsset(&ioreq2, 0, sizeof(ioreq2)); + + + ioreq2.irSectorNo = devUserAttr.sdkAttributes.sSecureDeleteDev1.dwSecureDeleteStartSector; + ioreq2.irSectorCount = devUserAttr.sdkAttributes.sSecureDeleteDev1.dwSecureDeleteNumOfSectors; + + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, devUserAttr.sdkAttributes.sSecureDeleteDev1.bPart); + + rc = DOCHWipeSectors(&ioreq2); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DochSDKInit(): Wipe-sectors operation NOT completed! \r\n"); + return rc; + } + + DBG_PRINT_ERR(FLZONE_API, "DochSDKInit(): Wipe-sectors operation completed successfully \r\n"); + } +#endif /*DOCH_NO_AUTO_WIPE_SECTORS*/ + /*Set global variable*/ + gSdkInitDone = DOCH_GLOBAL_BOOL_PATTERN; + + return DOCH_OK; +} + +/*----------------------------------------------------------------------*/ +/* D o c h S D K E x i t */ +/* */ +/* If the application ever exits, DochSDKExit should be called before */ +/* exit. */ +/* DochSDKExit flushes all buffers, closes all open files, powers down */ +/* the sockets and removes the interval timer. */ +/* */ +/* Parameters: */ +/* None */ +/* */ +/* Returns: */ +/* Nothing */ +/*----------------------------------------------------------------------*/ +void DochSDKExit(void) +{ + #ifdef DOCH_DMA_CONFIG + DMA_Params_S dmaParams; + #endif /*DOCH_DMA_CONFIG*/ + + doch_release_socket(0); + + #ifdef DOCH_DMA_CONFIG + /*Free the DMA channel*/ + dmaParams.bOpType = DOCH_DMA_FREE_CHANNEL; + DOCH_DMA_CONFIG(&dmaParams); + if(dmaParams.fDmaStatus != 0) + { + DBG_PRINT_ERR(FLZONE_API, "DochSDKExit(): DOCH_DMA_FREE_CHANNEL Failed\r\n"); + } + #endif /*DOCH_DMA_CONFIG*/ + + DOCH_SYS_FUNC_RELEASE; + + gConfigHWInitDone = 0; + gSdkInitDone = 0; +} + +/*----------------------------------------------------------------------*/ +/* D o c h R e g i s t e r S o c k e t */ +/* */ +/* Register a DOCH socket */ +/* */ +/* Parameters: */ +/* dwAddress : Address were DOCH socket is located */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failure */ +/*----------------------------------------------------------------------*/ +DOCH_Error DochRegisterSocket(FLDword dwAddress) +{ + DOCH_Error rc; + DOCH_InitSocket initSocket; + tffsset(&initSocket, 0, sizeof(initSocket)); + initSocket.nDeviceAddress = dwAddress; + + rc = doch_init_socket(0,initSocket); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DochSDKInit(): doch_init_socket Failed on socket #"); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("%d "), 0)); + DBG_PRINT_ERR(FLZONE_API, "with status : "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_AdapterNotFound; + } + + return DOCH_OK; +} + +#ifdef __cplusplus +} +#endif diff -urN linux-2.6.30.4-orig/drivers/block/tffs/_dochapi.h linux-2.6.30.4/drivers/block/tffs/_dochapi.h --- linux-2.6.30.4-orig/drivers/block/tffs/_dochapi.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/_dochapi.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,2625 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/***********************************************************************************/ +/* */ +/* Internal header file for doch_api module */ +/* */ +/***********************************************************************************/ + +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/version 7.0/TrueFFS FS/src/h3/_dochapi.h-arc $ + * + * Rev 1.24 Jan 31 2008 21:16:16 Yuli.Izrailov + * Added Quick Init support + * + * Rev 1.23 Dec 03 2007 18:54:24 einat.avidan + * Add flag for DochRecoverFromPowerLoss + * Remove flDOCHWipeSectorsByWriting + * + * Rev 1.22 Oct 30 2007 15:29:20 einat.avidan + * add new function flDOCHWipeSectorsByWriting + * + * Rev 1.21 Oct 22 2007 11:34:46 einat.avidan + * update copyrights header + * + * Rev 1.20 Oct 21 2007 15:28:26 einat.avidan + * fix compilation warnings + * + * Rev 1.19 Oct 11 2007 18:47:12 Einat.Avidan + * Replace global Boolean pattern with pattern in size of + * byte instead of dWord + * Add support for reporting internal errors + * add compilation flags for SOTP and SLPP + * + * Rev 1.18 Mar 22 2007 17:12:10 einat.avidan + * add SOTP + * + * Rev 1.17 Mar 13 2007 13:47:18 einat.avidan + * add support for SLPP + * + * Rev 1.16 Sep 11 2006 13:45:10 yaniv.iarovici + * Legal header added + * + * Rev 1.15 Sep 10 2006 10:02:40 Yaniv.Iarovici + * Change SA SDK sub-version to "1.51 Prelim2". + * + * Rev 1.14 Aug 24 2006 11:40:36 Yaniv.Iarovici + * Added 'DOCH_ACCESS_ALL_PARTITIONS' to structure 'DOCH_Access_Op'. + * + * Rev 1.13 Aug 16 2006 08:43:02 Yaniv.Iarovici + * change SA SDK sub-version to Fin4 + * Change DOCH_SECTOR_SIZE_BITS to bit-manipulation on DOCH_SECTOR_SIZE_BITS insead of value of 512 + * Add #define DOCH_MAX_DRQ_SUPPORTED to indicate max DRQ size supported by the SDK + * Change description of flDOCHGetPowerMode() and flDOCHSetPowerMode() to fit SW Spec 0.84 + * + * Rev 1.12 Aug 09 2006 17:27:42 Polina.Marimont + * initial for DOC Driver 1.0 + * + * Rev 1.10 Jul 03 2006 22:45:02 polina.marimont + * version change + * + * Rev 1.9 Jul 03 2006 22:12:32 polina.marimont + * version changed + * + * Rev 1.8 Jun 22 2006 16:56:32 Polina.Marimont + * version changed + * + * Rev 1.7 Jun 21 2006 18:23:34 Polina.Marimont + * 1. version update + * 2. set power mode function description updated + * + * Rev 1.6 Jun 18 2006 13:01:58 Polina.Marimont + * 1. version changed + * 2. power mode save function chaged + * + * Rev 1.5 Jun 14 2006 17:31:52 Polina.Marimont + * version updated + * + * Rev 1.4 May 30 2006 10:40:24 polina.marimont + * version change to 1.42 Pre 3 + * + * Rev 1.3 May 28 2006 12:48:26 polina.marimont + * version 1.42 Pre1 + * + * Rev 1.2 May 18 2006 14:40:46 polina.marimont + * PVCS inside + */ + +#ifndef _DOCHAPI +#define _DOCHAPI + +#include "_common.h" + +/***********************/ +/* SDK Version Number */ +/***********************/ +#define DochSDKVersion "0151" +#define DochSDKSubVersion "Pre2" + +/********************/ +/* Partitions */ +/********************/ + +/* Pattern to indicate a boolean global variable was set + (to deal with "naughty" compilers...)*/ +#define DOCH_GLOBAL_BOOL_PATTERN 0xCA + +/* Max number of paritions */ +#define DOCH_MAX_PARTITIONS 16 + +/*IPL partition*/ +#define DOCH_IPL_PARTITION 0 +#define IPL_PARTITION_SIZE_SECTORS 0x200 /*256KB in sectors*/ +#define IPL_PARTITION_SIZE_V_SECTORS 0x10 /* 8K KB sectors*/ + + +/********************/ +/* Various Defines */ +/********************/ + +/* On/Off definitions */ +#define DOCH_OFF 0 +#define DOCH_ON 1 + +/* size of DOCH data block in FLBytes */ +#define DOCH_SECTOR_SIZE_BITS 9 +#define DOCH_SECTOR_SIZE (1<irHandle & 0x0f) +#define DOCH_SET_SOCKET_TO_IOREQ_HANDLE(ioreq, socket) ((ioreq)->irHandle |= (socket)) + +#define DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) (FLByte)(((ioreq)->irHandle & 0xf0) >> 4) +#define DOCH_SET_PARTITION_TO_IOREQ_HANDLE(ioreq, part) ((ioreq)->irHandle = \ + ( ((part & 0xF) << 4) | ((ioreq)->irHandle & 0xFFFFFF0F)) ) + +/* Operation type (for long operations) */ +#define DOCH_NORMAL_OPERATION 0x00 +#define DOCH_IMMEDIATE_OPERATION 0x80 + +/* Data transfer modes */ +typedef enum { DOCH_DATA_XFER_MODE_SINGLE = 0x00, + DOCH_DATA_XFER_MODE_MULT = 0x01 +} DOCH_DataTransferMode; +/*Max supported DRQ*/ +#define DOCH_MAX_DRQ_SUPPORTED 4 + +/*ETFFS Alert Levels*/ +typedef enum { + DOCH_ALERT_LEVEL_CRASH = 0, /*Prints only errors that H3 can not recover from*/ + DOCH_ALERT_LEVEL_EMERGENCY = 1, /*Prints only important, but not lethal errors*/ + DOCH_ALERT_LEVEL_REPORT = 2, /*Prints basic report on H3 operations*/ + DOCH_ALERT_LEVEL_DEBUG = 3, /*Prints full report on H3 progress*/ + DOCH_ALERT_LEVEL_BORING = 4 /*Prints every operation done by H3*/ +} DOCH_AlertLevel; + +/* Power mode constants */ +typedef enum { + DOCH_PM_SET_NONE = 0x00, + DOCH_PM_SET_WORK_MODE = 0x01, + DOCH_PM_SET_INACTIVE_MODE = 0x02, + DOCH_PM_SET_BOTH_MODES = 0x03 +} DOCH_SetPowerMode; + +typedef enum { + DOCH_PM_WORK_MODE = 0x00, + DOCH_PM_INACTIVE_MODE = 0x04 +} DOCH_SelectedPowerMode; + +typedef enum { + DOCH_WM_NORMAL = 0x00, /*Same as ATA ACTIVE Mode*/ + DOCH_WM_LOW_FREQ = 0x01, /*Same as ATA IDLE Mode*/ + DOCH_WM_NORMAL_AND_AUTO_STBY = 0x02, + DOCH_WM_LOW_FREQ_AND_AUTO_STBY = 0x03 +} DOCH_WorkMode; + +typedef enum { + DOCH_IM_IDLE = 0x00, /*Same as ATA STANDBY Mode*/ + DOCH_IM_DPD = 0x10, /*Same as ATA SLEEP Mode*/ + DOCH_IM_IDLE_2_DPD = 0x20 /*No timeout IDLE ==> DPD */ +} DOCH_InactiveMode; + +#define DOCH_PM_SAVE_DEFAULT 0x10 /*Save power mode settings as device default*/ + +/* Custom Parameters Table */ +typedef enum { + DOCH_CP_BOOT_MODE = 0x00, /*Boot Mode (See DOCH_IPLModes)*/ + DOCH_CP_XIP_TEST_MODE = 0x01, /*XIP Test Modes (See DOCH_XIPTestModes)*/ + DOCH_CP_XIP_MAX_SIZE = 0x02, /*Max XIP Size*/ + DOCH_CP_XIP_ETFFS_SIZE = 0x03, /*Returns the size of the currently saved ETFFS (required for uploading the ETFFS)*/ + DOCH_CP_WORK_MODES = 0x04, /*Work Modes (Bit Field, see enum DOCH_CPWorkModes)*/ + DOCH_CP_SLOCK_CTRL = 0x05, /*Sticky Lock control (See DOCH_SlockCtrl)*/ + DOCH_CP_BYTE_SWAP_CTRL = 0x06, /*Byte Swap control (See DOCH_ByteSwapCtrl)*/ + DOCH_CP_FLASH_TEST_MODE = 0x07, /*Enable/Disable flash test mode (See DOCH_FlashTestModeCtrl)*/ + DOCH_CP_REPORT_ECC_MODE =0x08 /*Enable/Disable report of ECC errors (See DOCH_EccErrorCtrl)*/ +} DOCH_CustomParams; + +#define DOCH_CUSTOM_PARAM_TEMP 1 +#define DOCH_CUSTOM_PARAM_DEFAULT 0 + +/* IPL Modes */ +typedef enum { + DOCH_IPL_MODE_NORMAL_RAM = 0x0000, + DOCH_IPL_MODE_PAGED_RAM = 0x0001, + DOCH_IPL_MODE_VIRTUAL_RAM = 0x0002, + DOCH_IPL_MODE_CS_DELAY = 0x1000, /*Should be Or`ed with 0x0XX0, where bits 4-11 indicating delay*/ + DOCH_IPL_MODE_ADDRESS_SHIFT_IN_AFFECT = 0x2000, + DOCH_IPL_MODE_ACTIVE_SWAP_BYTES = 0x4000, + DOCH_IPL_MODE_8KB_WINDOW = 0x8000 +} DOCH_IPLModes; + +#define DOCH_IPL_WRITE_FIRST_CHUNK 0x80000000 /*Defines first chunk when writing IPL in chunks*/ + +/* XIP Test Modes */ /*No default value, will be cleared upon reset*/ +typedef enum { + DOCH_XIP_NORMAL = 0x0000, + DOCH_XIP_WRITEABLE = 0x0001, + DOCH_XIP_FILL_PATTERN = 0x0002, /*"M-Systems" and the rest with consecutive 16bit numbers*/ + DOCH_XIP_PIPELINE = 0x0003 /*Places the device in pipeline access mode*/ +} DOCH_XIPTestModes; + +typedef enum { + DOCH_WORK_MODES_BLOCK_SPI = 0x0002 /*Block SPI*/ +} DOCH_CPWorkModes; + +typedef enum { + DOCH_STICKY_LOCK_UNSET = 0x00, + DOCH_STICKY_LOCK_SET = 0x01 +} DOCH_SlockCtrl; + +typedef enum { + DOCH_BYTE_SWAP_UNSET = 0x00, + DOCH_BYTE_SWAP_SET = 0x01 +} DOCH_ByteSwapCtrl; + +typedef enum { + DOCH_DISABLE_FLASH_TEST_MODE = 0x00, + DOCH_ENABLE_FLASH_TEST_MODE = 0x01 +} DOCH_FlashTestModeCtrl; + +typedef enum { + DOCH_DISABLE_REPORT_ECC_ERRORS = 0x00, + DOCH_ENABLE_REPORT_ECC_ERRORS = 0x01 +} DOCH_EccErrorCtrl; + + +typedef enum { + DOCH_DLMCODE_DOWNLOAD = 0x01, /*Download is for immediate, temporary use*/ + DOCH_DLMCODE_DOWNLOAD_AND_SAVE = 0x07, /*Save downloaded code for immediate & future use*/ + DOCH_DLMCODE_DOWNLOAD_AND_LAST_SAVE = 0x87, /*Same as code 0x07, but marking this as the last permanent + download accepted by the device*/ + DOCH_DLMCODE_UPLOAD = 0xFF +} DOCH_DLMcodeModes; + +/* Set of access options for DOCH_EN_ACCESS_WPWD */ +typedef enum { DOCH_ACCESS_USER_PASSWORD = 0x00, + DOCH_ACCESS_MASTER_PASSWORD = 0x01, + DOCH_ACCESS_GATE_KEEPER = 0x02, + + DOCH_ACCESS_ALL_PARTITIONS = 0xFF +} DOCH_Access_Op; + +/*Defines for DOCHConfigHW*/ +/*------------------------*/ +typedef enum { + DOCH_BURST_WRITE_MODE_CTRL = 0x0, + DOCH_BURST_READ_MODE_CTRL = 0x1, + DOCH_IPL_CTRL = 0x2, + DOCH_WARM_BOOT_CTRL = 0x3, + DOCH_POWER_DOWN = 0x4, + DOCH_DMA_CTRL = 0x5, + DOCH_DMA_ENABLE = 0x6, + DOCH_DMA_NEGATION_CTRL = 0x7, + DOCH_SLOCK = 0x8, + DOCH_ENDIAN_CTRL = 0x9, + DOCH_OPERATION_MODE_CTRL = 0xA, + DOCH_POWER_MODE_CTRL = 0xB +} DOCH_HwConfigType; + +/* DOCH_NUM_OF_DCONFIGHW_ITEMS should be set to number of items in DOCH_HwConfigType*/ +#define DOCH_NUM_OF_DCONFIGHW_ITEMS 0xC + +/*IPL Control Register*/ +#define DOCH_IPL_WRITE_DISABLE 0x0000 +#define DOCH_IPL_WRITE_READY 0x0001 +#define DOCH_IPL_WRITE_ENABLE 0x0002 + +#define DOCH_IPL_ALL_CS_ENABLED 0x0000 +#define DOCH_IPL_CLOSE_2LOW_IPLS 0x0010 +#define DOCH_IPL_CLOSE_2HIGH_IPLS 0x0020 +#define DOCH_IPL_CLOSE_ALL_IPLS 0x0030 + +/*Warm Boot Register*/ +#define DOCH_WARM_RST_POLARITY_LOW 0x0000 +#define DOCH_WARM_RST_POLARITY_HIGH 0x0001 + +#define DOCH_WARM_RST_BURST_ON 0x0000 +#define DOCH_WARM_RST_BURST_NO_CHNG 0x0002 + +/*Deep Power Down Mode Register*/ +#define DOCH_DPD_PIN_POL_LOW 0x0000 +#define DOCH_DPD_PIN_POL_HIGH 0x0001 + +#define DOCH_DPD_PIN_DISABLED 0x0000 +#define DOCH_DPD_PIN_ENABLED 0x0002 + +#define DOCH_DPD_WAKEUP_HOST_CE 0x0000 +#define DOCH_DPD_WAKEUP_ASYNC_CLK 0x0100 + +/*DMA Control Register*/ +#define DOCH_DMA_REQ_DISABLE 0x0000 +#define DOCH_DMA_REQ_ENABLE 0x0001 + +#define DOCH_DMA_REQ_POL_HIGH 0x0000 +#define DOCH_DMA_REQ_POL_LOW 0x0002 + +#define DOCH_DMA_REQ_LEVEL 0x0000 +#define DOCH_DMA_REQ_EDGE 0x0004 + +/*SLOCK Control Register*/ +#define DOCH_SLOCK_ACTIVE 0x0001 +#define DOCH_SLOCK_OFF 0x0000 + +/*Burst write/read mode control*/ +#define DOCH_BURST_DISABLE 0x0000 +#define DOCH_BURST_ENABLE 0x0002 + +#define DOCH_BURST_HOLD_1_CLK 0x0000 +#define DOCH_BURST_HOLD_2_CLK 0x2000 + +#define DOCH_BURST_LEN_4_CYC 0x0000 +#define DOCH_BURST_LEN_8_CYC 0x0800 +#define DOCH_BURST_LEN_16_CYC 0x1000 +#define DOCH_BURST_LEN_32_CYC 0x1800 + +/*Endian Control Register*/ +#define DOCH_END_SWAP_OFF 0x0000 +#define DOCH_END_SWAP_ON 0x0101 + +/*Operation Mode Register*/ +#define DOCH_NON_PIPE_ACCESS 0x00 +#define DOCH_PIPE_ACCESS 0x01 + +#define DOCH_NO_ADDR_SHIFT 0x00 +#define DOCH_ADDR_SHIFT 0x02 + +/*Power Mode Register*/ +#define DOCH_POWER_MODE_DPD 0x0001 + +/*Environment variables*/ +typedef enum { + DOCH_ENV_VERIFY_WRITE = 0x01, /* Verifies every written sector by reading it back from device */ + DOCH_ENV_ATA_DEBUG = 0x02, /* Retrieve debug buffer from device after completion of ATA command */ + DOCH_ENV_BLOCK_SPI = 0x03, /* Block SPI */ + DOCH_ENV_NO_ATA_TIMEOUT = 0x04, /* Disable ATA command timeout */ + DOCH_ENV_AUTO_DPD_BY_HOST = 0x05, /* Host automatically enters device to DPD after every command*/ + DOCH_ENV_QUICK_INIT = 0x06 /* For utilities. Make it possible not to seek for second device */ +} DOCH_EnVars; + +/*Flags for read/write operations using DMA/Burst*/ +#define DOCH_USE_DMA 0x01 +#define DOCH_USE_BURST 0x02 + +/* Strings lengths */ +#define DOCH_PASS_KEY_LEN 0x80 +#define DOCH_PASS_KEY_LEN_NO_NULL (H3_PASS_KEY_LEN-1) +#define DOCH_SER_NO_LEN 0x14 +#define DOCH_MODEL_NO_LEN 0x28 +#define DOCH_PROG_NAME_LEN 0x10 +#define DOCH_PROG_VER_LEN 0x8 + +/* DOCHRecoverFromPowerLoss flags */ +#define DOCH_DO_NOT_REINIT_MASTER 0x1 + + +/* DOCH error codes */ +/*------------------*/ +#define DOCH_ATA_ERROR_BASE 0x0 +#define DOCH_SDK_ERROR_BASE 0x100 +#define DOCH_FS_ERROR_BASE 0x200 + +typedef enum { DOCH_OK = 0, + + /*ATA Error codes*/ + + DOCH_ATA_NO_ERROR = DOCH_ATA_ERROR_BASE + 0x00, + DOCH_ATA_ERROR_MEDIA_ERROR_DETECTED = DOCH_ATA_ERROR_BASE + 0x01, /*ATA-4*/ + DOCH_ATA_ERROR_ADDRESS_MARK_NOT_FOUND = DOCH_ATA_ERROR_BASE + 0x01, /*Repeat last operation*/ + DOCH_ATA_ERROR_TRACK_0_NOT_FOUND = DOCH_ATA_ERROR_BASE + 0x02, /*Protection violation*/ + DOCH_ATA_ERROR_NO_MEDIA = DOCH_ATA_ERROR_BASE + 0x02, /*ATA-4*/ + DOCH_ATA_ERROR_ABORT = DOCH_ATA_ERROR_BASE + 0x04, /*Always need to be supplied*/ + DOCH_ATA_ERROR_MEDIA_CHANGE_REQUESTED = DOCH_ATA_ERROR_BASE + 0x08, /*Not to use for now*/ + DOCH_ATA_ERROR_ID_NOT_FOUND = DOCH_ATA_ERROR_BASE + 0x10, /*Passing partition boundary*/ + DOCH_ATA_ERROR_MEDIA_CHANGE_DETECTED = DOCH_ATA_ERROR_BASE + 0x20, /*Not to use for now*/ + DOCH_ATA_ERROR_WRITE_PROTECTED = DOCH_ATA_ERROR_BASE + 0x40, /*on writes - only if we run out of space*/ + DOCH_ATA_ERROR_UNCORRECTABLE_DATA = DOCH_ATA_ERROR_BASE + 0x40, /*on reads - possible for unrecoverable ECC - should not be returned by write routines*/ + DOCH_ATA_ERROR_ICRC = DOCH_ATA_ERROR_BASE + 0x80, /*on DMA xfers - to leave for now*/ + + /*SDK Error Codes*/ + DOCH_TimedOut = DOCH_SDK_ERROR_BASE, + DOCH_GeneralFailure = DOCH_SDK_ERROR_BASE + 5, + DOCH_AdapterNotFound = DOCH_SDK_ERROR_BASE + 6, + DOCH_DeviceTurnedOff = DOCH_SDK_ERROR_BASE + 7, + DOCH_BadParameter = DOCH_SDK_ERROR_BASE + 10, + DOCH_DriveNotAvailable = DOCH_SDK_ERROR_BASE + 15, + DOCH_DriveNotReady = DOCH_SDK_ERROR_BASE + 20, + DOCH_NotEnoughMemory = DOCH_SDK_ERROR_BASE + 25, + DOCH_ReadFault = DOCH_SDK_ERROR_BASE + 30, + DOCH_WriteFault = DOCH_SDK_ERROR_BASE + 31, + DOCH_VerifyFault = DOCH_SDK_ERROR_BASE + 32, + DOCH_ProtectionFault = DOCH_SDK_ERROR_BASE + 33, + DOCH_UnknownCmd = DOCH_SDK_ERROR_BASE + 35, + DOCH_DiskNotFound = DOCH_SDK_ERROR_BASE + 40, + DOCH_PartitionNotFound = DOCH_SDK_ERROR_BASE + 45, + DOCH_PartitionLimitExceeded = DOCH_SDK_ERROR_BASE + 50, + DOCH_FeatureNotSupported = DOCH_SDK_ERROR_BASE + 55, + DOCH_ATABusyNotCleared = DOCH_SDK_ERROR_BASE + 60, + DOCH_ATANotReady = DOCH_SDK_ERROR_BASE + 61, + DOCH_ATAErrorDetected = DOCH_SDK_ERROR_BASE + 65 + +} DOCH_Error; + + +/* IOCTL Codes */ +typedef enum { + /*Get Info*/ + SDK_IDENTIFY_DISKONCHIP_DEVICE = 0x200, + SDK_GET_RESET_STATUS = 0x201, + SDK_NOTIFY_RESET = 0x202, + SDK_NOTIFY_PLATFORM_RESUMED = 0x203, + SDK_GET_PARTITION_INFO = 0x204, + SDK_SET_DISK_USER_ATTR = 0x205, + SDK_GET_DISK_USER_ATTR = 0x206, + SDK_GET_CONFIG_DATA = 0x207, + SDK_SET_CONFIG_DATA = 0x208, + + /*Media*/ + SDK_SET_DEFAULT_PARTITION = 0x210, + SDK_SET_DATA_XFER_MODE = 0x211, + SDK_OPTIMIZE_MEDIA = 0x212, + SDK_DELETE_PARTITIONS = 0x213, + SDK_ADD_PARTITION = 0x214, + SDK_UNFORMAT_DEVICE = 0x215, + SDK_WRITE_IPL = 0x216, + SDK_READ_IPL = 0x217, + + /*IO*/ + SDK_READ_PARTITION_SECTORS = 0x220, + SDK_WRITE_PARTITION_SECTORS = 0x221, + SDK_WRITE_AND_LOCK = 0x222, + SDK_WIPE_SECTORS = 0x223, + SDK_FREE_SECTORS = 0x224, + SDK_PREPARE_FOR_WRITE = 0x225, + SDK_WIPE_SECTORS_BY_WRITING = 0x226, + + /*Flexi-Flash*/ + SDK_WRITE_FLEXI_FAST = 0x230, + SDK_WRITE_FLEXI_NORMAL = 0x231, + SDK_REWRITE_FLEXI_NORMAL = 0x232, + + /*Hash*/ + SDK_READ_WITH_HASH_VERIFY = 0x240, + SDK_READ_HASH = 0x241, + SDK_WRITE_HASH = 0x242, + + /*Protection*/ + SDK_ACCESS_PART_WITH_PWD = 0x250, + SDK_DISABLE_PART_ACCESS = 0x251, + SDK_SET_PART_PROTECTION = 0x252, + SDK_SET_PART_USER_ATTR = 0x253, + SDK_GET_PART_USER_ATTR = 0x254, + + /*PKI*/ + SDK_PKI_HOST = 0x260, + SDK_PKI_DOCH = 0x261, + SDK_PKI_VERIFY_HOST_KEY = 0x262, + + /*Custom Parameters*/ + SDK_GET_CUSTOM_PARAM = 0x270, + SDK_SET_CUSTOM_PARAM = 0x271, + + /*Atomic Read/Write Sequence*/ + SDK_ATOMIC_WRITE_SEQ = 0x280, + + /*Algorithms*/ + SDK_REPORT_SUPP_ALG = 0x290, + SDK_REPORT_ALG_CAPAB = 0x291, + SDK_SET_ALG_MODE = 0x292, + + /*Hash*/ + SDK_AUTO_HASH_CTRL = 0x2A0, + SDK_READ_CALC_HASH = 0x2A1, + SDK_WRITE_CALC_HASH = 0x2A2, + SDK_READ_ORIG_HASH = 0x2A3, + SDK_WRITE_GIVEN_HASH = 0x2A4, + SDK_START_HASH_STREAM_CALC = 0x2A5, + SDK_READ_HASH_STREAM_CALC = 0x2A6, + SDK_RETURN_RAND_NUMS = 0x2A7, + SDK_SET_HASH_KEY = 0x2A8, + + /*General (Control/Configuration)*/ + SDK_SET_POWER_MODE = 0x2B0, + SDK_GET_POWER_MODE = 0x2B1, + SDK_HW_CONFIG = 0x2B2, + SDK_RECOVER_FROM_POWER_LOSS = 0x2B3, + SDK_RESET_SOCKET = 0x2B4, + SDK_SET_ENV_VAR = 0x2B5, + SDK_CLEAR_ATA_INTERRUPT = 0x2B6, +#ifndef FL_SLPP + SDK_GET_PHYSICAL_ADDRESS = 0x2B7 +#else /*FL_SLPP*/ + SDK_GET_PHYSICAL_ADDRESS = 0x2B7, + /*SLPP Specific*/ + SDK_SLPP_UNLOCK_RANGE = 0x2C0, + SDK_SLPP_UNLOCK_ENTIRE_PARTITION = 0x2C1, + SDK_SLPP_LOCK_RANGE = 0x2C2, + SDK_SLPP_STICKY_LOCK_RANGE = 0x2C3, + SDK_SLPP_REPORT_LOCKED_RANGES = 0x2C4 +#endif /*FL_SLPP*/ + +} SDKFunctionNo; + +/* runtime socket init data */ +typedef struct { + unsigned int nDeviceAddress; +} DOCH_InitSocket; + +/* Access layer routines registration structure */ +typedef struct { + unsigned char (*hal_get_ata_reg_user) (volatile unsigned char *base, int reg); + void (*hal_set_ata_reg_user) (volatile unsigned char *base, int reg, unsigned int val); + unsigned short(*hal_get_ctrl_reg_user) (volatile unsigned char *base, int reg); + void (*hal_set_ctrl_reg_user) (volatile unsigned char *base, int reg, unsigned int val); + int (*hal_blk_read_user) (volatile unsigned char *base, unsigned char *buf, int sectors); + int (*hal_blk_write_user) (volatile unsigned char *base, unsigned char *buf, int sectors); + int (*hal_release_user) (int socketNo); +} DOCH_BusAccess_routines; + +/********************/ +/* API Defines */ +/********************/ + +/* set of DOCH ATA registers */ +typedef enum { + DOCH_DATA_REG = 0x00, + DOCH_ERROR_REG = 0x01, + DOCH_FEATURES_REG = 0x01, + DOCH_SECTOR_CNT_REG = 0x02, + DOCH_SECTOR_NO_REG = 0x03, + DOCH_CYLINDER_LOW_REG = 0x04, + DOCH_CYLINDER_HIGH_REG = 0x05, + DOCH_DRIVE_HEAD_REG = 0x06, + DOCH_STATUS_REG = 0x07, + DOCH_COMMAND_REG = 0x07, + DOCH_ALT_STATUS_REG = 0x0E, + DOCH_CONTROL_REG = 0x0E +} DOCH_Reg; + +/* ATA registers structure */ +typedef struct { FLByte bFeaturesError; /* DOCH_FEATURES_REG or DOCH_ERROR_REG */ + FLByte bSectorCount; /* DOCH_SECTOR_CNT_REG */ + FLByte bSectorNumber; /* DOCH_SECTOR_NO_REG */ + FLByte bCylLow; /* DOCH_CYLINDER_LOW_REG */ + FLByte bCylHigh; /* DOCH_CYLINDER_HIGH_REG */ + FLByte bDriveHead; /* DOCH_DRIVE_HEAD_REG */ + FLByte bCommandStatus; /* DOCH_COMMAND_REG or DOCH_STATUS_REG*/ + FLByte bContorlAltStatus; /* DOCH_CONTROL_REG or DOCH_ALT_STATUS_REG*/ +} DOCH_Registers; + +/* Set of operation codes for PassThru */ +typedef enum { DOCH_PASSTHRU_NO_DATA = 0x00, + DOCH_PASSTHRU_DATA_IN = 0x01, + DOCH_PASSTHRU_DATA_OUT = 0x02 +} DOCH_PassThru_Op; + +typedef enum { DOCH_PASSTHRU_NO_INT = 0x00, + DOCH_PASSTHRU_USE_INT = 0x04 + +} DOCH_PassThru_Int; + + +/*OPTIMIZE_MEDIA*/ +#define DOCH_OPTIMIZE_BY_PREPARE_FOR_WRITE 0 +#define DOCH_OPTIMIZE_DEFAULT 1 + +typedef enum { + SET_DEFAULT_PARTITION_TEMP = 0x0, + SET_DEFAULT_PARTITION_PERM = 0x1 +} DOCH_DefaultPartSet; + +typedef enum { + DOCH_FAST_PARTITOIN_DELETE = 0x0, + DOCH_COMPLETE_PARTITION_DELETE = 0x8 +} DOCH_DeletePartitionsMode; + + +/******************************************************************************/ +/* + * Partition Info structure, sub-structures and ENUMS + */ +/******************************************************************************/ + +/*Partition dwCommandFlagsOrStatuses Offsets*/ +#define DOCH_CFSO_FAST_AREA_SIZE_TYPE 8 +#define DOCH_CFSO_USER_AUTHENTICATED 16 +#define DOCH_CFSO_PERM_LOCKED 17 +#define DOCH_CFSO_MASTER_AUTHENTICATED 18 +#ifdef FL_SOTP +#define DOCH_CFSO_SOTP_LOCKED 19 +#endif /*FL_SOTP*/ +#define DOCH_CFSO_HW_LOCK_ASSERTED 30 +#define DOCH_CFSO_SW_LOCK_ASSERTED 31 + +/*Partition dwCommandFlagsOrStatuses Bits*/ +#define DOCH_CFSB_FAST_AREA_SIZE_TYPE 0x00000100 +#define DOCH_CFSB_USER_AUTHENTICATED 0x00010000 +#define DOCH_CFSB_PERM_LOCKED 0x00020000 +#define DOCH_CFSB_MASTER_AUTHENTICATED 0x00040000 +#ifdef FL_SOTP +#define DOCH_CFSB_SOTP_LOCKED 0x00080000 +#endif /*FL_SOTP*/ +#define DOCH_CFSB_HW_LOCK_ASSERTED 0x40000000 +#define DOCH_CFSB_SW_LOCK_ASSERTED 0x80000000 + +/*Partition Attribute1 Offsets*/ +#define DOCH_PA1O_PARTITION_TYPE 0 +#define DOCH_PA1O_PERFORMANCE_CTRL 8 +#define DOCH_PA1O_PAGE_SIZE_EXP 16 +#define DOCH_PA1O_HASH_TYPE 24 + +/*Partition Attribute1 Bits*/ +#define DOCH_PA1B_PARTITION_TYPE 0x000000FF +#define DOCH_PA1B_PERFORMANCE_CTRL 0x00000F00 +#define DOCH_PA1B_PAGE_SIZE_EXP 0x000F0000 +#define DOCH_PA1B_HASH_TYPE 0x3F000000 + +/*Partition Attribute2 Offsets*/ +#define DOCH_PA2O_PROTECTION_TYPE 0 +#define DOCH_PA2O_USER_MODE 6 +#define DOCH_PA2O_GUEST_MODE 9 +#define DOCH_PA2O_MASTER_CTRL 12 +#define DOCH_PA2O_ENCRYPT_TYPE 15 +#define DOCH_PA2O_OTP_BIT 21 +#define DOCH_PA2O_LOCK_CTRL 22 +#define DOCH_PA2O_MAX_AUTH_ATTEMPTS 24 + +/*Partition Attribute2 Bits*/ +#define DOCH_PA2B_PROTECTION_TYPE 0x00000007 /*DOCH_ProtectionType*/ +#define DOCH_PA2B_USER_MODE 0x000001C0 /*DOCH_PartitionAccessMode*/ +#define DOCH_PA2B_GUEST_MODE 0x00000E00 /*DOCH_PartitionAccessMode*/ +#define DOCH_PA2B_MASTER_CTRL 0x00007000 /*DOCH_PartitionAccessMode*/ +#define DOCH_PA2B_ENCRYPT_TYPE 0x00038000 /*DOCH_EncryptType*/ +#define DOCH_PA2B_OTP_BIT 0x00200000 +#define DOCH_PA2B_LOCK_CTRL 0x00C00000 /*DOCH_LockControl*/ +#define DOCH_PA2B_MAX_AUTH_ATTEMPTS 0x0F000000 + +/* Structure that holds various partition data*/ +typedef struct { + FLByte bDevice; /*On which device (0/1) the partition reside*/ +} DOCH_PartitionAttr; + +/*Partition formatting info*/ + +/*API exported for partition preporties*/ +typedef struct { + FLDword dwProtectionType; /*DOCH_ProtectionType*/ + FLDword dwUserAccessMode; /*DOCH_PartitionAccessMode*/ + FLDword dwGuestAccessMode; /*DOCH_PartitionAccessMode*/ + FLDword dwMasterControl; /*DOCH_PartitionAccessMode*/ + FLDword dwEncryptionType; /*DOCH_EncryptType*/ + FLDword dwLockControl; /*DOCH_LockControl*/ + FLDword dwMaxNumOfAuthAttempts; /*0 = Unlimited number*/ + FLByte bPasskey[0x80]; /*ASCII*/ +} DOCH_PartitionProtectionAPI; + +typedef enum { + DOCH_PASSKEY_VALID = 0x01, /* Passkey in DOCH_PartitionProtectionAPI is valid */ + DOCH_ATTRIBUTES_VALID = 0x02, /* All attributes in DOCH_PartitionProtectionAPI besides passkey are valid */ + DOCH_LOCK_AS_OTP = 0x04, /* Lock the partition for writing */ + DOCH_SEQUENTIAL_OTP = 0x08 /* Enable sequential OTP partition, must be always set with DOCH_LOCK_AS_OTP*/ +} DOCH_PartitionProtectioValidity; + +/*Partition Info structure*/ + +typedef struct { + FLByte bReserved1[0x4]; + FLDword dwCommandFlagsOrStatuses; /*Dynamic info*/ + FLDword partitionAttributes1; + FLDword partitionAttributes2; + FLDword nPartitionSize; /*In Sectors*/ + FLDword nFastAreaSize; /*In Sectors or Percent. for IPL partition: size reported in XIP*/ + FLWord wFastAreaFactor; /*Exponent*/ + FLByte bReserved2[0x2]; + FLDword wPartitionStartSector; + FLWord wCurrentSectorsPerTrack; + FLWord wDefaultSectorsPerTrack; + FLWord wCurrentCylinders; + FLWord wDefaultCylinders; + FLWord wCurrentHeads; + FLWord wDefaultHeads; + FLByte bReserved3[0x4]; /*44-48*/ + FLDword dwSOTPoffset; + FLByte bReserved4[0xC]; + FLWord wFastAreaSectorsInErasableUnit; /*Exponent*/ + FLWord wNormalAreaSectorsInErasableUnit; /*Exponent*/ + FLWord wRecommendedSectorsPerCluster; + FLWord wFastMaxRelatedSectors; + FLWord wNormalMaxRelatedSectors; + FLByte bReserved5[0xB6]; + FLByte bPartitionKey[0x80]; + FLByte bReserved6[0x80]; +} DOCH_PartitionInfo; + +typedef struct { + FLDword dwPartitionType; /*DCOH_PartitionType*/ + FLDword dwPerformanceControl; /*DOCH_PerformanceControl*/ + FLDword dwPageSizeExp; /*DOCH_PageSizeExp*/ + FLDword dwHashType; /*DOCH_HashType*/ + FLDword dwFastAreaSizeType; /*DOCH_FastAreaType*/ + FLDword dwProtectionType; /*DOCH_ProtectionType*/ + FLDword dwUserAccessMode; /*DOCH_PartitionAccessMode*/ + FLDword dwGuestAccessMode; /*DOCH_PartitionAccessMode*/ + FLDword dwMasterControl; /*DOCH_PartitionAccessMode*/ + FLDword dwEncryptionType; /*DOCH_EncryptType*/ + FLDword dwLockControl; /*DOCH_LockControl*/ + FLDword dwOtpEnabled; /*DOCH_OTPBit*/ + FLDword dwMaxNumOfAuthAttempts; /*0 = Unlimited number*/ + FLNative nPartitionSize; /*In Sectors*/ + FLNative nFastAreaSize; /*In Sectors or Percent**/ + FLWord wFastAreaFactor; /*Exponent*/ + FLByte bPasskey[0x80]; /*ASCII*/ +#ifdef FL_SOTP + FLByte bSOTP; /*SOTP partition*/ +#endif /*FL_SOTP*/ +} DOCH_PartitionFormatInfoAPI; + +/*Partition formatting info*/ +typedef struct { + FLByte bReserved1[0x4]; + FLDword dwCommandFlagsOrStatuses; + FLDword partitionAttributes1; + FLDword partitionAttributes2; + FLDword nPartitionSize; /*In Sectors*/ + FLDword nFastAreaSize; /*In Sectors or Percent*/ + FLWord wFastAreaFactor; /*Exponent*/ + FLByte bReserved2[0x12]; + FLDword dwValidity; /*DOCH_PartitionProtectioValidity*/ + FLByte bReserved3[0xD0]; + FLByte bPasskey[0x80]; + FLByte bReserved4[0x80]; +} DOCH_PartitionFormatInfo; + +/*Device dwCommandFlagsOrStatuses Offsets*/ +#define DOCH_DCFSO_CURRENT_XFER_MODE 0 +#define DOCH_DCFSO_CURRENT_MULTI_SECTOR 8 +#define DOCH_DCFSO_HW_LOCK_ASSERTED 30 +#define DOCH_DCFSO_SW_LOCK_ASSERTED 31 + +/*Device dwCommandFlagsOrStatuses Bits*/ +#define DOCH_DCFSB_CURRENT_XFER_MODE 0x00000007 +#define DOCH_DCFSB_CURRENT_MULTI_SECTOR 0x00000F00 +#define DOCH_DCFSB_HW_LOCK_ASSERTED 0x40000000 +#define DOCH_DCFSB_SW_LOCK_ASSERTED 0x80000000 + +/*Device Attributes1 Offsets*/ +#define DOCH_DA1O_SUPPORTED_XFER_MODES_BMP 0 +#define DOCH_DA1O_MAX_MULTI_SEC_XFER_SIZE 8 +#define DOCH_DA1O_SUPPORT_48_BITS 31 + +/*Device Attributes1 Bits*/ +#define DOCH_DA1B_SUPPORTED_XFER_MODES_BMP 0x000000FF +#define DOCH_DA1B_MAX_MULTI_SEC_XFER_SIZE 0x00000F00 +#define DOCH_DA1B_SUPPORT_48_BITS 0x80000000 + +/*Gate Keeper Attributes Offsets*/ +#define DOCH_DA2O_AUTH_TYPE 0 /*DOCH_DeviceAuthType*/ +#define DOCH_DA2O_GUEST_ACCESS_MODE 9 /*DOCH_DeviceAccessMode*/ +#define DOCH_DA2O_MASTER_CONTROL 12 /*DOCH_DeviceAccessMode*/ +#define DOCH_DA2O_MAX_AUTH_ATTEMPTS 24 + +/*Gate Keeper Attributes Bits*/ +#define DOCH_DA2B_AUTH_TYPE 0x00000003 +#define DOCH_DA2B_GUEST_ACCESS_MODE 0x00000E00 +#define DOCH_DA2B_MASTER_CONTROL 0x00007000 +#define DOCH_DA2B_MAX_AUTH_ATTEMPTS 0x0F000000 + +/*Authentication types*/ +typedef enum { + DOCH_DEVICE_AUTH_NONE = 0, + DOCH_DEVICE_AUTH_PWD = 1, + DOCH_DEVICE_AUTH_RSA = 2 +} DOCH_DeviceAuthType; +/*Access modes*/ +typedef enum { + DOCH_DEVICE_ACCESS_MODE_FULL = 0, + DOCH_DEVICE_ACCESS_MODE_RO = 1, + DOCH_DEVICE_ACCESS_MODE_NONE = 2 +} DOCH_DeviceAccessMode; + +#define DOCH_CONFIGURATION_EXISTS_SIGN 0x1F2E3D4C + +typedef struct { + FLWord wVersion; + FLWord wVersionCompatability; + FLDword dwCommandFlagsOrStatuses; + FLDword dwDiskAttributes1; + FLDword dwRservedGateKeeperAttr; + FLDword dwMiscFlags; + FLByte bReserved2[0xC]; + FLByte bUniqueID[0x10]; + FLByte bReserved3[0x10]; + FLByte bSerialNumber[0x14]; + FLByte bModelNumber[0x28]; + FLWord wTotalNumOfPartitions; /*0=IPL not present, 1=Only IPL Present, ... 16=IPL partition + 15 user partitions (MAX)*/ + FLWord wDefaultPartitionNumber; + FLDword dwUnformattedCapacity; /*In Sectors*/ + FLDword dwConfigurationPartitionExistsSign; + FLDword dwETFFSVER; + FLDword dwReservedConfigPartitionSize; /*In Sectors*/ + FLByte bProgrammerName[0x10]; + FLByte bProgrammerVersion[0x8]; + FLDword dwUnitSize; /* In Sectors */ + FLByte bReserved5[0x54]; /*In Sectors*/ + FLByte bReservedGateKeeperKey[0x80]; + FLByte bReserved6[0x80]; +} DOCH_DeviceInfo; + +/*Enums*/ +/*=====*/ +typedef enum { DOCH_PRT_TYPE_NORMAL = 0, /*normal*/ + DOCH_PRT_TYPE_PAGED = 1, /*paged*/ + DOCH_PRT_TYPE_PAGED_DIGEST = 2, /*paged + keeps digest information*/ + DOCH_PRT_TYPE_PAGED_COMPRESSED = 3, /*paged + keeps data in compressed form */ + DOCH_PRT_TYPE_PAGED_DIGEST_COMPRESSED= 4 /*paged + keeps data in compressed form + digest*/ +} DCOH_PartitionType; + + +/*Performance Control*/ +typedef enum { DOCH_NORMAL_PERFORMANCE = 0, /*MLC*/ + DOCH_FIRM_FLASH_OPTIMIZE = 1, /*Rigid MLC/SLC division, fast area field defines division*/ + DOCH_FLEXI_FLASH_OPTIMIZE= 2 /*Adaptive MLC/SLC division, fast area field defines size of spare capacity for performance optimization*/ +} DOCH_PerformanceControl; + +/*Page size exponent (for paged partitions)*/ +typedef enum { DOCH_PAGE_SIZE_512B = 0, + DOCH_PAGE_SIZE_1KB = 1, + DOCH_PAGE_SIZE_2KB = 2, + DOCH_PAGE_SIZE_4KB = 3, + DOCH_PAGE_SIZE_8KB = 4, + DOCH_PAGE_SIZE_16KB = 5, + DOCH_PAGE_SIZE_32KB = 6 +} DOCH_PageSizeExp; + +/*Page size exponent (for paged partitions)*/ +typedef enum { DOCH_HASH_TYPE_SHA1 = 0 +} DOCH_HashType; + +/*Fast Area Type*/ +typedef enum { DOCH_FAST_AREA_TYPE_SECTORS = 0, + DOCH_FAST_AREA_TYPE_PERCENT = 1 +} DOCH_FastAreaType; + +/*Protection Type*/ +typedef enum { DOCH_PARTITION_NOT_PROTECTED = 0, + DOCH_PARTITION_PWD_PROTECTED = 1, + DOCH_PARTITION_RSA_PROTECTED = 2, + DOCH_PARTITION_SLPP_PROTECTED = 3 +} DOCH_ProtectionType; + +#define DOCH_MAX_PWD_ATTEMPTS 5 /*"0" for Unlimited # of attempts*/ + +/*Partition access mode*/ +typedef enum { + DOCH_PART_ACCESS_MODE_FULL = 0, + DOCH_PART_ACCESS_MODE_RO = 1, + DOCH_PART_ACCESS_MODE_NONE = 2 +} DOCH_PartitionAccessMode; + +/*Encryption Type*/ +typedef enum { DOCH_ENCRYPT_NONE = 0, /*Partition is not encrypted*/ + DOCH_ENCRYPT_AES_CTR = 1, /*Partition is AES-encrypted, CTR mode*/ + DOCH_ENCRYPT_RC4 = 2 /*Partition is RC4-encrypted*/ +} DOCH_EncryptType; + + +/*Lock Control*/ +typedef enum { DOCH_LOCK_NOT_ACTIVE = 0,/*LOCK# signal or soft-lock do not affect the access to this partition*/ + DOCH_LOCK_ACTIVE = 1 /*After LOCK# signal is active or soft-lock is written, access to partition*/ + /*can not be authenticated. If access has already been authenticated, it remains*/ +} DOCH_LockControl; + +/*OTP Bit*/ +typedef enum { DOCH_OTP_BIT_OFF = 0, + DOCH_OTP_BIT_ON = 1 +} DOCH_OTPBit; + +typedef enum { + PARTITION_TYPE_IPL = 0x00, + PARTITION_TYPE_BDTL = 0x01, + PARTITION_TYPE_BINARY = 0x02, + PARTITION_TYPE_OTP = 0x03 +} DOCH_PartitionType; + +/******************************************************************************/ +/* + * Partition Access structure + */ +/******************************************************************************/ + +/*Structure for DOCH_VSCMD_EXT_DEVICE_CTRL::DOCH_SET_PARTITION_PROTECTION + and DOCH_VSCMD_EXT_SECURITY_CTRL::DOCH_EN_ACCESS_WPWD*/ +typedef struct { + FLByte bReserved1[0x100]; + FLByte bPassword[0x80]; + FLByte bReserved2[0x80]; +} DOCH_PartitionAcessPassword; + +/******************************************************************************/ +/* + * PKI structures + */ +/******************************************************************************/ + +#define DOCH_CHLNG_SIZE 0x40 +#define DOCH_PKI_KEY_SIZE 0x80 + +/*Structure for DOCH_VSCMD_EXT_SECURITY_CTRL::DOCH_TX_HOST_PUBLICKEY*/ +typedef struct { + FLWord wVersion; + FLByte bReserved1[0xBE]; + FLByte bHostRandomChallange[DOCH_CHLNG_SIZE]; + FLByte bHostPublicKey[DOCH_PKI_KEY_SIZE]; + FLByte bReservedForLargerKey[0x80]; +} DOCH_HostPublicKey; + +/*Structure for DOCH_VSCMD_EXT_SECURITY_CTRL::DOCH_RX_DOCH_PUBLICKEY*/ +typedef struct { + FLWord wVersion; + FLByte bReserved1[0x3E]; + FLByte bHostRandomChallangeByDochPrivateKey[DOCH_CHLNG_SIZE]; + FLByte bReserved2[0x40]; + FLByte bDochRandomChallange[DOCH_CHLNG_SIZE]; + FLByte bDochPublicKey[DOCH_PKI_KEY_SIZE]; + FLByte bReservedForLargerKey[0x80]; +} DOCH_DochPublicKey; + +/*Structure for DOCH_VSCMD_EXT_SECURITY_CTRL::DOCH_VERIFY_HOST_KEY*/ +typedef struct { + FLWord wVersion; + FLByte bReserved1[0x3E]; + FLByte bDochRandomChallangeByHostPrivateKey[DOCH_CHLNG_SIZE]; + FLByte bReserved2[0x180]; +} DOCH_VerifyHostKey; + +/******************************************************************************/ +/* + * Algorithm structures + */ +/******************************************************************************/ + +/*Supported algorithms retrieval structure*/ +/*----------------------------------------*/ +typedef struct { + FLWord wVersion; + FLByte bReserved1[0x2]; + FLDword wSymmetricAlgorithmsSupported; /*Bitmap: AES...*/ + FLDword wAsymmetricAlgorithmsSupported; /*Bitmap: RSA...*/ + FLDword wHashSchemesSupported; /*Bitmap: SHA-1...*/ + FLDword wRNGSchemesSupported; /*Bitmap: TrueRandom...*/ + FLDword wDecompressionSchemesSupported; /*Bitmap: LZ77...*/ + FLDword wCompressionSchemesSupported; /*Bitmap: LZ77...*/ + FLByte bReserved2[0x1E4]; +} DOCH_supportedAlgorithms; + +/*Specific algorithm capabilities retrieval structure and sub-structures*/ +/*----------------------------------------------------------------------*/ +typedef struct { + FLDword dwSize; + FLDword dwCalcTime; /*For the key, in nano*/ +} KeyAttr; + +typedef struct { + FLByte bName[8]; /*In ASCII*/ + FLWord wKeySizes; /*Bitmap of key sizes supported by this mode*/ + FLByte bReserved[0x6]; +} ModeAttr; + +typedef struct { + FLWord wVersion; + FLByte bReserved1[0x2]; + FLByte bAlgorithmName[0x10]; /*In ASCII*/ + FLWord wNumOfKeySizesSupported; + FLWord wNumOfModesSupported; + FLByte bReserved2[0x8]; + KeyAttr keysAttributes[0x8]; + ModeAttr modesAttributes[0x18]; +} DOCH_AlgorithmCapabilities; + +/*Enums for HASH control*/ +/*----------------------*/ +typedef enum { + DOCH_HASH_REINITIALIZE = 0x00, + DOCH_HASH_CONTINUE = 0x01, + DOCH_HASH_CONTINUE_ACCUM = 0x00, + DOCH_HASH_STOP_ACCUM = 0x01, + DOCH_HASH_DONT_RETURN_DATA = 0x00, + DOCH_HASH_RETURN_ACCUM_DIGEST = 0x02 +} DOCH_HashStartStream; + +typedef enum { + DOCH_HASH_DECRYPTION_KEY = 0x00, + DOCH_HASH_ENCRYPTION_KEY = 0x01, + + /*For Decryption*/ + DOCH_HASH_USE_DOCH_PUBLIC_KEY = 0x00, + DOCH_HASH_USE_HOST_PUBLIC_KEY = 0x01, + DOCH_HASH_USE_PARTITION_PUBLIC_KEY = 0x02, + + /*For Encryption*/ + DOCH_HASH_USE_DOCH_PRIVATE_KEY = 0x00, + DOCH_HASH_USE_HOST_PRIVATE_KEY = 0x01 +} DOCH_HashSetKey; + +#ifdef FL_SLPP +/*SLPP Specific*/ +/* should be replaced by the real values/structures once they are defined!!! */ + +#define DOCH_SLPP_MAX_LOCK_RANGES 16 + +typedef enum { + DOCH_SLPP_UNLOCKED_RANGE = 1, + DOCH_SLPP_PERM_LOCKED_RANGE = 2 +} DOCH_SLPPRangeType; + +typedef struct { + FLDword dwRangeStartSector; + FLDword dwRangeSizeInSectors; + FLDword lockType; +} DOCH_SLPPRange; + +typedef struct { + FLDword numOfActiveRanges; + DOCH_SLPPRange rangeParams[DOCH_SLPP_MAX_LOCK_RANGES]; + FLByte spare[0x200 - (DOCH_SLPP_MAX_LOCK_RANGES*sizeof(DOCH_SLPPRange)) - sizeof(FLDword)]; +} DOCH_SLPPReport; + +typedef struct { + FLDword dwRangeStartSector; + FLDword dwRangeSizeInSectors; + FLByte passkey[0x80]; + FLByte spare[0x178]; +} DOCH_SLPPRangeRequestSector; +#endif /*FL_SLPP*/ + +/********************/ +/* API Routines */ +/********************/ + +/*----------------------------------------------------------------------*/ +/* f l D O C H S e t D e f a u l t P a r t i t i o n */ +/* */ +/* Set default partition for Standard-ATA commands */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irCount : SET_DEFAULT_PARTITION_TEMP */ +/* SET_DEFAULT_PARTITION_PERM */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_SET_DEFAULT_PARTITION */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHSetDefaultPartition(ioreq) bdCallDOCH(SDK_SET_DEFAULT_PARTITION, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H S e t D a t a T r a n s f e r M o d e */ +/* */ +/* Set Data transfer mode */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : Requested data transfer mode: */ +/* DOCH_DATA_XFER_MODE_SINGLE */ +/* DOCH_DATA_XFER_MODE_MULT */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_SET_DATA_XFER_MODE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHSetDataTransferMode(ioreq) bdCallDOCH(SDK_SET_DATA_XFER_MODE, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H I d e n t i f y D i s k O n C h i p D e v i c e */ +/* */ +/* Returns general information about the Device */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : DOCH_IDENTIFY_FROM_FLASH */ +/* DOCH_IDENTIFY_EXISTANCE */ +/* irData : Address of DOCH_DeviceInfo struct */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_IDENTIFY_DISKONCHIP_DEVICE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHIdentifyDiskOnChipDevice(ioreq) bdCallDOCH(SDK_IDENTIFY_DISKONCHIP_DEVICE, ioreq) +#define DOCH_IDENTIFY_FROM_FLASH 0x0 +#define DOCH_IDENTIFY_EXISTANCE DRIVE_HEAD_OPT1 + + +/*----------------------------------------------------------------------*/ +/* f l D O C H G e t R e s e t S t a t u s */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_GET_RESET_STATUS */ +/* */ +/* Returns: */ +/* irCount : 0 = No reset since last query */ +/* 1 = The device has been reset since last*/ +/* query */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHGetResetStatus(ioreq) bdCallDOCH(SDK_GET_RESET_STATUS, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H N o t i f y R e s e t */ +/* */ +/* Notify the Device on an upcoming reset initiated by the Host. */ +/* Host should NOT perform actual reset before this command completes */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_NOTIFY_RESET */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHNotifyReset(ioreq) bdCallDOCH(SDK_NOTIFY_RESET, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H N o t i f y P l a t f o r m R e s u m e d */ +/* */ +/* Notify the Device that there was a reset, */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_NOTIFY_PLATFORM_RESUMED */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHNotifyPlatformResumed(ioreq) bdCallDOCH(SDK_NOTIFY_PLATFORM_RESUMED, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H P a r t i t i o n I n f o */ +/* */ +/* Get information about a specific partition. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Address of user buffer to read partition */ +/* information into. */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_GET_PARTITION_INFO */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHPartitionInfo(ioreq) bdCallDOCH(SDK_GET_PARTITION_INFO, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H D e l e t e P a r t i t i o n s */ +/* */ +/* Delete range of partitions */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irFlags : DOCH_NORMAL_OPERATION */ +/* DOCH_IMMEDIATE_OPERATION */ +/* irCount : First partition to delete */ +/* irLength : Last partition to delete */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_DELETE_PARTITIONS */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHDeletePartitions(ioreq) bdCallDOCH(SDK_DELETE_PARTITIONS, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H U n f o r m a t */ +/* */ +/* Unformats DOCH device. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_DELETE_PARTITIONS */ +/* DOCH_SET_DISK_USER_ATTR */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHUnformatDevice(ioreq) bdCallDOCH(SDK_UNFORMAT_DEVICE, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H A d d P a r t i t i o n */ +/* */ +/* Adds a partition */ +/* The new partition is created on existing un-formatted disk capacity */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_ADD_PARTITION */ +/* */ +/* Returns: */ +/* irCount : Number of the created partition */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHAddPartition(ioreq) bdCallDOCH(SDK_ADD_PARTITION, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H W r i t e I P L */ +/* */ +/* Writes IPL partition. */ +/* Sets IPL mode and size. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irFlags : DOCH_IPL_MODE_NORMAL_RAM */ +/* DOCH_IPL_MODE_PAGED_RAM */ +/* DOCH_IPL_MODE_VIRTUAL_RAM */ +/* DOCH_IPL_MODE_CS_DELAY */ +/* DOCH_IPL_MODE_ADDRESS_SHIFT_IN_AFFECT */ +/* DOCH_IPL_MODE_ACTIVE_SWAP_BYTES */ +/* DOCH_IPL_MODE_8KB_WINDOW */ +/* DOCH_IPL_WRITE_FIRST_CHUNK */ +/* irCount : Max IPL size */ +/* Up to 32KB for Normal Mode */ +/* Up to 128KB for Virtual Mode */ +/* Up to 256KB for Paged Mode */ +/* irLength : Current chunk length (in sectors) */ +/* irData : Pointer to user buffer (length defined by */ +/* irLength) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* DOCH_VSCMD_WRITE_PARTITION */ +/* ATA sub-command: */ +/* DOCH_SET_CUSTOM_PARAM */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHWriteIPL(ioreq) bdCallDOCH(SDK_WRITE_IPL, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H R e a d I P L */ +/* */ +/* Read specified sectors from IPL partition. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : First sector to read */ +/* irLength : Number of sectors to read */ +/* irData : Pointer to user buffer (length defined by */ +/* irLength) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* DOCH_VSCMD_WRITE_PARTITION */ +/* ATA sub-command: */ +/* DOCH_SET_CUSTOM_PARAM */ +/* */ +/* Returns: */ +/* irFlags : DOCH_IPL_MODE_NORMAL_RAM */ +/* DOCH_IPL_MODE_PAGED_RAM */ +/* DOCH_IPL_MODE_VIRTUAL_RAM */ +/* DOCH_IPL_MODE_CS_DELAY */ +/* DOCH_IPL_MODE_ADDRESS_SHIFT_IN_AFFECT */ +/* DOCH_IPL_MODE_ACTIVE_SWAP_BYTES */ +/* DOCH_IPL_MODE_8KB_WINDOW */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHReadIPL(ioreq) bdCallDOCH(SDK_READ_IPL, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H R e a d P a r t i t i o n S e c t o r s */ +/* */ +/* Reads sectors by sector no from a specific partition */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Address of user buffer to read into */ +/* irSectorNo : First sector no. to read. */ +/* irSectorCount : Number of consecutive sectors to read */ +/* irFlags : DOCH_USE_DMA */ +/* DOCH_USE_BURST */ +/* Note: 4 methods of data transfer are */ +/* available: */ +/* Normal transfer */ +/* DMA transfer */ +/* Burst transfer */ +/* DMA & Burst transfer */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_READ_PARTITION */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors NOT read (in case of an */ +/* error - this number may not be accurate) */ +/*----------------------------------------------------------------------*/ +#define flDOCHReadPartitionSectors(ioreq) bdCallDOCH(SDK_READ_PARTITION_SECTORS, ioreq) + +/*----------------------------------------------------------------------*/ +/* D O C H W r i t e P a r t i t i o n S e c t o r s */ +/* */ +/* Writes sectors by sector no to a specific partition */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Address of user buffer to write from */ +/* irSectorNo : First sector no. to write */ +/* irSectorCount : Number of consecutive sectors to write */ +/* irFlags : DOCH_USE_DMA */ +/* DOCH_USE_BURST */ +/* Note: 4 methods of data transfer are */ +/* available: */ +/* Normal transfer */ +/* DMA transfer */ +/* Burst transfer */ +/* DMA & Burst transfer */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_WRITE_PARTITION */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors NOT read (in case of an */ +/* error - this number may not be accurate) */ +/*----------------------------------------------------------------------*/ +#define flDOCHWritePartitionSectors(ioreq) bdCallDOCH(SDK_WRITE_PARTITION_SECTORS, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H W r i t e A n d L o c k */ +/* */ +/* Writes sectors by sector no to a specific partition */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Address of user buffer to write from */ +/* irSectorNo : First sector no. to write */ +/* irSectorCount : Number of consecutive sectors to write */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_WRITE_PARTITION */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors NOT read (in case of an */ +/* error - this number may not be accurate) */ +/*----------------------------------------------------------------------*/ +#define flDOCHWriteAndLock(ioreq) bdCallDOCH(SDK_WRITE_AND_LOCK, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H F r e e S e c t o r s */ +/* */ +/* Marks absolute sectors by sector no. as free to be written */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irSectorNo : First sector no. to delete */ +/* irSectorCount : Number of consecutive sectors to delete */ +/* irFlags : DOCH_NORMAL_OPERATION */ +/* DOCH_IMMEDIATE_OPERATION */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_ERASE_PARTITION_SECTORS */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors actually deleted */ +/*----------------------------------------------------------------------*/ +#define flDOCHFreeSectors(ioreq) bdCallDOCH(SDK_FREE_SECTORS, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H W i p e S e c t o r s */ +/* */ +/* Securely erase data in sectors */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irSectorCount : Number of sectors to transfer (1..2). */ +/* irData : 1..2 sectors with following layout: */ +/* - 1st 8bytes - reserved as zeroes */ +/* - (FLDWord) : First sector to delete */ +/* (FLDWord) : # of sectors to delete */ +/* - (FLDWord) : Second sector to delete */ +/* (FLDWord) : # of sectors to delete */ +/* - ... */ +/* - (FLDWord) : Nth sector to delete */ +/* (FLDWord) : # of sectors to delete */ +/* * Last transaction should have both start */ +/* and length fields set to 0. */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_SECURE_ERASE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHWipeSectors(ioreq) bdCallDOCH(SDK_WIPE_SECTORS, ioreq) + + +/*----------------------------------------------------------------------*/ +/* f l D O C H P r e p a r e F o r W r i t e */ +/* */ +/* Signal to DOCH that these sectors are going to be over-written in */ +/* following write command */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irSectorNo : First sector no. to write */ +/* irSectorCount : Number of consecutive sectors to write */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_OPTIMIZE_PARTITION_SECTORS */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHPrepareForWrite(ioreq) bdCallDOCH(SDK_PREPARE_FOR_WRITE, ioreq) + +/* Flexi-Flash */ + +/*----------------------------------------------------------------------*/ +/* f l D O C H W r i t e F l e x i F a s t */ +/* */ +/* Flexi-Flash Write Fast */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Address of user buffer to write from */ +/* irSectorNo : First sector no. to write */ +/* irSectorCount : Number of consecutive sectors to write */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_WRITE_FLEXI */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors actually written */ +/*----------------------------------------------------------------------*/ +#define flDOCHWriteFlexiFast(ioreq) bdCallDOCH(SDK_WRITE_FLEXI_FAST, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H W r i t e F l e x i N o r m a l */ +/* */ +/* Flexi-Flash Write Normal */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Address of user buffer to write from */ +/* irSectorNo : First sector no. to write */ +/* irSectorCount : Number of consecutive sectors to write */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_WRITE_FLEXI */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors actually written */ +/*----------------------------------------------------------------------*/ +#define flDOCHWriteFlexiNormal(ioreq) bdCallDOCH(SDK_WRITE_FLEXI_NORMAL, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H R e W r i t e N o r m a l */ +/* */ +/* Flexi-Flash Re-Write Normal */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Address of user buffer to write from */ +/* irSectorNo : First sector no. to write */ +/* irSectorCount : Number of consecutive sectors to write */ +/* */ +/* ATA command: */ +/* */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors actually re-written */ +/*----------------------------------------------------------------------*/ +#define flDOCHReWriteFlexiNormal(ioreq) bdCallDOCH(SDK_REWRITE_FLEXI_NORMAL, &ioreq) + + +/*----------------------------------------------------------------------*/ +/* f l D O C H M a n a g e A t o m i c W r i t e S e q */ +/* */ +/* Manage atomic write sequence per partition */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irCount : DOCH_START_ATOMIC_WRITE */ +/* DOCH_FINISH_ATOMIC_WRITE */ +/* DOCH_ABORT_ATOMIC_WRITE */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_ATOMIC_WRITE_SEQUENCE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHManageAtomicWriteSeq(ioreq) bdCallDOCH(SDK_ATOMIC_WRITE_SEQ, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H A c c e s s P a r t W i t h P w d */ +/* */ +/* Insert the protection key in order to remove the protection of the */ +/* specified partition or the entire media */ +/* Partition could be authenticated both by user and master password */ +/* the last successful authentication supersedes the previous one. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* 0xF - for authenticating the entire device */ +/* irFlags : Authentication Type */ +/* : DOCH_ACCESS_USER_PASSWORD */ +/* DOCH_ACCESS_MASTER_PASSWORD */ +/* DOCH_ACCESS_GATE_KEEPER */ +/* irData : pointer to an DOCH_PartitionAcessPassword struct */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_ACCESS_CONTROL */ +/* ATA sub-command: */ +/* DOCH_EN_ACCESS_WPWD */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHAccessPartWithPwd(ioreq) bdCallDOCH(SDK_ACCESS_PART_WITH_PWD, ioreq) + + +/*----------------------------------------------------------------------*/ +/* f l D O C H D i s a b l e P a r t A c c e s s */ +/* */ +/* Remove the protection key making the partition protected again */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* 0xF - for disabling access to the entire*/ +/* media */ +/* irFlags : Authentication to withdraw */ +/* DOCH_ACCESS_USER_PASSWORD */ +/* DOCH_ACCESS_MASTER_PASSWORD */ +/* DOCH_ACCESS_GATE_KEEPER */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_ACCESS_CONTROL */ +/* ATA sub-command: */ +/* DOCH_DISABLE_ACCESS */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHDisablePartAccess(ioreq) bdCallDOCH(SDK_DISABLE_PART_ACCESS, ioreq) + + +/*----------------------------------------------------------------------*/ +/* f l D O C H S e n d H o s t P u b l i c K e y */ +/* */ +/* Host sends its public key for this partition & random challenge */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* 0xF - for disabling access to the entire */ +/* media */ +/* irFlags : DOCH_ACCESS_USER_PASSWORD */ +/* DOCH_ACCESS_MASTER_PASSWORD */ +/* DOCH_ACCESS_GATE_KEEPER */ +/* irData : Pointer to DOCH_HostPublicKey structure */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_ACCESS_CONTROL */ +/* ATA sub-command: */ +/* DOCH_TX_HOST_PUBLICKEY */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHSendHostPublicKey(ioreq) bdCallDOCH(SDK_PKI_HOST, ioreq) + + +/*----------------------------------------------------------------------*/ +/* f l D O C H R e c e i v e D o c h P u b l i c K e y */ +/* */ +/* DOCH sends its public key, host's random challenge encrypted by DOCH */ +/* private key, and DOCH's random challenge to host */ +/* */ +/* Parameters: */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* 0xF - for disabling access to the entire */ +/* media */ +/* irFlags : DOCH_ACCESS_USER_PASSWORD */ +/* DOCH_ACCESS_MASTER_PASSWORD */ +/* DOCH_ACCESS_GATE_KEEPER */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_ACCESS_CONTROL */ +/* ATA sub-command: */ +/* DOCH_RX_DOCH_PUBLICKEY */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHReceiveDochPublicKey(ioreq) bdCallDOCH(SDK_PKI_DOCH, ioreq) + + +/*----------------------------------------------------------------------*/ +/* f l D O C H V e r i f y H o s t K e y */ +/* */ +/* Host sends DOCH's random challenge encrypted by host's private key */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irCount : DOCH_ACCESS_USER_PASSWORD */ +/* DOCH_ACCESS_MASTER_PASSWORD */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_ACCESS_CONTROL */ +/* ATA sub-command: */ +/* DOCH_VERIFY_HOST_KEY */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHVerifyHostKey(ioreq) bdCallDOCH(SDK_PKI_VERIFY_HOST_KEY, ioreq) + + +/*----------------------------------------------------------------------*/ +/* f l D O C H S e t P a r i t i o n P r o t e c t i o n */ +/* */ +/* Set partition properties (attributes/passkey) . */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Pointer to DOCH_PartitionProtectionAPI */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_SET_PARTITION_PROTECTION */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHSetParitionProtection(ioreq) bdCallDOCH(SDK_SET_PART_PROTECTION, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H S e t P a r i t i o n U s e r A t t r i b u t e s */ +/* */ +/* Set partition user attributes . */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Pointer to DOCH_PartitionUserAttr */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_SET_PARTITION_USER_ATTR */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHSetParitionUserAttributes(ioreq) bdCallDOCH(SDK_SET_PART_USER_ATTR, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H G e t P a r i t i o n U s e r A t t r i b u t e s */ +/* */ +/* Get partition user attributes . */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Pointer to DOCH_PartitionUserAttr */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_GET_PARTITION_USER_ATTR */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHGetParitionUserAttributes(ioreq) bdCallDOCH(SDK_GET_PART_USER_ATTR, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H S e t D i s k U s e r A t t r i b u t e s */ +/* */ +/* Set disk user attributes . */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irData : Pointer to 1 sector of data */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_SET_DISK_USER_ATTR */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHSetDiskUserAttributes(ioreq) bdCallDOCH(SDK_SET_DISK_USER_ATTR, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H G e t D i s k U s e r A t t r i b u t e s */ +/* */ +/* Get disk user attributes . */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irData : Pointer to 1 sector of data */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_GET_DISK_USER_ATTR */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHGetDiskUserAttributes(ioreq) bdCallDOCH(SDK_GET_DISK_USER_ATTR, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H G e t C o n f i g u r a t i o n D a t a */ +/* */ +/* Read the device configuration data. No authentication is required */ +/* for calling this command, but the fields containing keys in the */ +/* configuration data will be masked by ETFFS using zeros. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irData : Pointer to 1..3 sector(s) of data. */ +/* irCount : Sector offset in the configuration data to start */ +/* reading from. */ +/* irLength : Number of sectors of configuration data to read. */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_GET_CONFIGURATION_DATA */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHGetConfigurationData(ioreq) bdCallDOCH(SDK_GET_CONFIG_DATA, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H S e t C o n f i g u r a t i o n D a t a */ +/* */ +/* Save the device configuration data. Calling this command will */ +/* succeed only if there are no partitions present on the media */ +/* (including partition 0). */ +/* You should use this command in the process of duplicating DiskOnChip */ +/* device to make sure all configuration data of the original device */ +/* have been duplicated to the new device. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irData : Pointer to 1..3 sector(s) of data. */ +/* irCount : Sector offset in the configuration data to start */ +/* reading from. */ +/* irLength : Number of sectors of configuration data to read. */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_SET_CONFIGURATION_DATA */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHSetConfigurationData(ioreq) bdCallDOCH(SDK_SET_CONFIG_DATA, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H O p t i m i z e M e d i a */ +/* */ +/* Performs garbage collection. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* */ +/* irCount : DOCH_OPTIMIZE_SINGLE_PARTITION */ +/* DOCH_OPTIMIZE_WHOLE_MEDIA */ +/* */ +/* irLength : DOCH_OPTIMIZE_BY_PREPARE_FOR_WRITE */ +/* based on information collected during previous */ +/* PREPARE FOR WRITE commands */ +/* DOCH_OPTIMIZE_DEFAULT */ +/* performs default optimization of the whole */ +/* partition or media */ +/* irFlags : DOCH_NORMAL_OPERATION */ +/* DOCH_IMMEDIATE_OPERATION */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_OPTIMIZE_MEDIA */ +/* */ +/* Returns: */ +/* irLength : Actual number of sectors available for writes */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHOptimizeMedia(ioreq) bdCallDOCH(SDK_OPTIMIZE_MEDIA, ioreq) + + +/*----------------------------------------------------------------------*/ +/* f l D O C H G e t C u s t o m P a r a m e t e r */ +/* */ +/* Returns 16-bit custom DOCH parameter */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irCount : Parameter# (see DOCH_CustomParams) */ +/* irFlags : DOCH_CUSTOM_PARAM_DEFAULT - default value */ +/* DOCH_CUSTOM_PARAM_TEMP - current (saved) value*/ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_GET_CUSTOM_PARAM */ +/* */ +/* Returns: */ +/* irSectorNo : Custom parameter value (16-Bit) */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHGetCustomParameter(ioreq) bdCallDOCH(SDK_GET_CUSTOM_PARAM, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H S e t C u s t o m P a r a m e t e r */ +/* */ +/* Sets 16-bit custom DOCH parameter */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : Custom Parameter Number (DOCH_CustomParams) */ +/* irSectorNo : Custom Parameter Value (16-Bit) */ +/* irFlags : DOCH_CUSTOM_PARAM_DEFAULT - default value */ +/* DOCH_CUSTOM_PARAM_TEMP - current (saved) value*/ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_SET_CUSTOM_PARAM */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHSetCustomParameter(ioreq) bdCallDOCH(SDK_SET_CUSTOM_PARAM, ioreq) + + +/*----------------------------------------------------------------------*/ +/* f l D O C H A u t o H a s h C o n t r o l */ +/* */ +/* Enable/Disable Auto Hash Read/Write */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : AUTO_HASH_ENABLE */ +/* AUTO_HASH_DISABLE */ +/* irLength : AUTO_HASH_READ */ +/* AUTO_HASH_WRITE */ +/* irFlags : DOCH_HASH_NO_ENCRYPTION */ +/* DOCH_HASH_ENCRYPT_BY_KEY */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_SECURITY_CTRL */ +/* ATA sub-command: */ +/* DOCH_AUTO_HASH_CONTROL */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHAutoHashControl(ioreq) bdCallDOCH(SDK_AUTO_HASH_CTRL, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H R e a d C a l c u l a t e d H a s h */ +/* */ +/* Command for Paged partitions */ +/* Transfers to host digest(s) calculated from data on the flash. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_READ_CALCULATED_HASH */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHReadCalculatedHash(ioreq) bdCallDOCH(SDK_READ_CALC_HASH, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H W r i t e C a l c u l a t e d H a s h */ +/* */ +/* Command for Paged partitions */ +/* No data is transfered. Digest(s) calculated from data in the flash */ +/* are stored to the dedicated area on flash. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : DOCH_HASH_NO_ENCRYPTION */ +/* DOCH_HASH_ENCRYPT_BY_KEY */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_WRITE_CALCULATED_HASH */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHWriteCalculatedHash(ioreq) bdCallDOCH(SDK_WRITE_CALC_HASH, ioreq) + + +/*----------------------------------------------------------------------*/ +/* f l D O C H R e a d O r i g i n a l H a s h */ +/* */ +/* Command for Paged partitions */ +/* Transfers to host digest(s) stored previously on dedicated area on */ +/* flash */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : DOCH_HASH_NO_ENCRYPTION */ +/* DOCH_HASH_ENCRYPT_BY_KEY */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_READ_ORIGINAL_HASH */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHReadOriginalHash(ioreq) bdCallDOCH(SDK_READ_ORIG_HASH, ioreq) + + +/*----------------------------------------------------------------------*/ +/* f l D O C H W r i t e G i v e n H a s h */ +/* */ +/* Command for Paged partitions */ +/* Transfers from host digest(s) and stores them to the dedicated area */ +/* on flash */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : DOCH_HASH_NO_ENCRYPTION */ +/* DOCH_HASH_ENCRYPT_BY_KEY */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_WRITE_GIVEN_HASH */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHWriteGivenHash(ioreq) bdCallDOCH(SDK_WRITE_GIVEN_HASH, ioreq) + + +/*----------------------------------------------------------------------*/ +/* f l D O C H R e p o r t S u p p o r t e d A l g o r i t h m s */ +/* */ +/* Report supported algorithms */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_SECURITY_CTRL */ +/* ATA sub-command: */ +/* DOCH_REPORT_SUPPORTED_ALGORITHMS */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHReportSupportedAlgorithms(ioreq) bdCallDOCH(SDK_REPORT_SUPP_ALG, ioreq) + + +/*----------------------------------------------------------------------*/ +/* f l D O C H G e t A l g o r i t h m C a p a b i l i t i e s */ +/* */ +/* Get algorithms capabilities */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_SECURITY_CTRL */ +/* ATA sub-command: */ +/* DOCH_GET_ALGORITHM_CAPABILITIES */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHGetAlgorithmCapabilities(ioreq) bdCallDOCH(SDK_REPORT_ALG_CAPAB, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H S e t A l g o r i t h m M o d e */ +/* */ +/* Set algorithms mode */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : bits 0..7 - Algorithm Category */ +/* bits 8..15 - Algorithm # in category */ +/* bits 16..24 - Mode index */ +/* bits 24..31 - Key size index */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_SECURITY_CTRL */ +/* ATA sub-command: */ +/* DOCH_SET_ALGORITHM_MODE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHSetAlgorithmMode(ioreq) bdCallDOCH(SDK_SET_ALG_MODE, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H S t a r t H a s h S t r e a m C a l c u l a t i o n */ +/* */ +/* Restart/Continue hash stream calculation */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : bits 0..7 - Algorithm Category */ +/* bits 8..15 - Algorithm # in category */ +/* irLength : HASH_REINITIALIZE */ +/* HASH_CONTINUE */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_SECURITY_CTRL */ +/* ATA sub-command: */ +/* DOCH_START_HASH_STREAM_CALC */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHStartHashStreamCalculation(ioreq) bdCallDOCH(SDK_START_HASH_STREAM_CALC, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H R e a d S t o p H a s h S t r e a m C a l c */ +/* */ +/* Read/Stop hash stream calculation */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : DOCH_HASH_CONTINUE_ACCUM */ +/* DOCH_HASH_STOP_ACCUM */ +/* irLength : DOCH_HASH_DONT_RETURN_DATA */ +/* DOCH_HASH_RETURN_ACCUM_DIGEST */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_SECURITY_CTRL */ +/* ATA sub-command: */ +/* DOCH_READ_STOP_HASH_STREAM_CALC */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHReadStopHashStreamCalc(ioreq) bdCallDOCH(SDK_READ_HASH_STREAM_CALC, ioreq) + + +/*----------------------------------------------------------------------*/ +/* f l D O C H R e t u r n R a n d om N u m b e r s */ +/* */ +/* Return random numbers */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : bits 0..7 - Algorithm Category */ +/* bits 8..15 - Algorithm # in category */ +/* irLength : # of 32-Bit random numbers to generate */ +/* (max is 64, e.g full sector) */ +/* irData : Pointer to 1 sector of data which will hold */ +/* the number of requested random numbers */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_SECURITY_CTRL */ +/* ATA sub-command: */ +/* DOCH_RETURN_RANDOM_NUMBERS */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHReturnRandomNumbers(ioreq) bdCallDOCH(SDK_RETURN_RAND_NUMS, ioreq) + + +/*----------------------------------------------------------------------*/ +/* f l D O C H S e t H a s h K e y */ +/* */ +/* Set hash key */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : DOCH_HASH_DECRYPTION_KEY */ +/* DOCH_HASH_ENCRYPTION_KEY */ +/* irLength : DOCH_HASH_USE_DOCH_PUBLIC_KEY */ +/* DOCH_HASH_USE_HOST_PUBLIC_KEY */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_SECURITY_CTRL */ +/* ATA sub-command: */ +/* DOCH_SET_KEYS */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHSetHashKey(ioreq) bdCallDOCH(SDK_SET_HASH_KEY, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H G e t P o w e r M o d e */ +/* */ +/* Retrieve device power mode */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_SET_POWER_MODE */ +/* */ +/* Returns: */ +/* irFlags : */ +/* DOCH_PM_WORK_MODE */ +/* DOCH_PM_INACTIVE_MODE */ +/* irCount : */ +/* Bits 0..1 : Work Mode */ +/* DOCH_WM_NORMAL */ +/* DOCH_WM_LOW_FREQ */ +/* DOCH_WM_NORMAL_AND_AUTO_STBY */ +/* DOCH_WM_LOW_FREQ_AND_AUTO_STBY */ +/* Bits 4..5 : Inactive Mode */ +/* DOCH_IM_IDLE */ +/* DOCH_IM_DPD */ +/* DOCH_IM_IDLE_2_DPD */ +/* irLength : Value of timeout for automatic transfer to */ +/* Inactive mode (0 = disabled) */ +/* Timer value is in milliseconds. */ +/* If Inactive mode is "Standby to DPD" timer */ +/* resolution is 100 ms. */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHGetPowerMode(ioreq) bdCallDOCH(SDK_GET_POWER_MODE, ioreq) + +/*----------------------------------------------------------------------*/ +/* D O C H S e t P o w e r M o d e */ +/* */ +/* Set device power mode */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irFlags : */ +/* Bits 0..1 - which mode(s) should be set */ +/* DOCH_PM_SET_WORK_MODE */ +/* DOCH_PM_SET_INACTIVE_MODE */ +/* DOCH_PM_SET_BOTH_MODES */ +/* DOCH_PM_SET_NONE */ +/* Bit 2 - which mode device should pass to after set */ +/* DOCH_PM_WORK_MODE */ +/* DOCH_PM_INACTIVE_MODE */ +/* Bit 4 */ +/* DOCH_PM_SAVE_DEFAULT */ +/* (Save new settings as default settings ) */ +/* irCount : */ +/* Bits 0..1 : Work Mode to be set */ +/* DOCH_WM_NORMAL */ +/* DOCH_WM_LOW_FREQ */ +/* DOCH_WM_NORMAL_AND_AUTO_STBY */ +/* DOCH_WM_LOW_FREQ_AND_AUTO_STBY */ +/* Bits 4..5 : Inactive Mode to be set */ +/* DOCH_IM_IDLE */ +/* DOCH_IM_DPD */ +/* DOCH_IM_IDLE_2_DPD */ +/* irLength : Value of timeout for automatic transfer to */ +/* Inactive mode (0 = disabled) */ +/* Timer value is in milliseconds. */ +/* If Inactive mode is "Standby to DPD" timer */ +/* resolution is 100 ms. */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_SET_POWER_MODE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHSetPowerMode(ioreq) bdCallDOCH(SDK_SET_POWER_MODE, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H C o n f i g H W */ +/* */ +/* Control HW registers */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irFlags : HW Configuration type */ +/* (See DOCH_HwConfigType for values) */ +/* irLength : HW configuration type dependant */ +/* */ +/* ATA command: */ +/* NONE */ +/* ATA sub-command: */ +/* NONE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHConfigHW(ioreq) bdCallDOCH(SDK_HW_CONFIG, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H R e c o v e r F r o m P o w e r L o s s */ +/* */ +/* Set last known values of DOCH control registers back to device after */ +/* power loss was detected. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* NONE */ +/* ATA sub-command: */ +/* NONE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHRecoverFromPowerLoss(ioreq) bdCallDOCH(SDK_RECOVER_FROM_POWER_LOSS, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H S e t E n v V a r */ +/* */ +/* Set environment variable. */ +/* Available environment variables are listed in DOCH_EnVars. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based, if relevant) */ +/* irFlags : Environment variable */ +/* */ +/* irLength : Value to set */ +/* */ +/* ATA command: */ +/* NONE */ +/* ATA sub-command: */ +/* NONE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#ifdef __cplusplus +extern "C" { +#endif +DOCH_Error flDOCHSetEnvVar(IOreq* ioreq); +#ifdef __cplusplus +} +#endif + +/*----------------------------------------------------------------------*/ +/* f l D O C H C l e a r I R Q */ +/* */ +/* Clear the ATA interrupt. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* NONE */ +/* ATA sub-command: */ +/* NONE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHClearIRQ(ioreq) bdCallDOCH(SDK_CLEAR_ATA_INTERRUPT, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H G e t P h y s i c a l A d d r e s s */ +/* */ +/* Retrieve physical address of the socket. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* NONE */ +/* ATA sub-command: */ +/* NONE */ +/* */ +/* Returns: */ +/* irCount : Socket Physical Address */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHGetPhysicalAddress(ioreq) bdCallDOCH(SDK_GET_PHYSICAL_ADDRESS, ioreq) + +#ifndef flFormatFS +/*----------------------------------------------------------------------*/ +/* f l F o r m a t F S */ +/* */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (0, 1, ...) */ +/* bits 11-8 - Logical partition in Flash partition (zero based)*/ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irSectorNo : First absolute sector of logical partition */ +/* (if bit 13 is set) */ +/* irSectorCount : Number of sectors in logical partition */ +/* (if bit 13 is set) */ +/* irData : Address of the FATFormatParams structure */ +/* irFlags : */ +/* bit 14 - FL_DO_NOT_UPDATE_MBR */ +/* bit 13 - FL_MEDIA_WITHOUT_MBR */ +/* bit 12 - FL_MOUNT_ON_GIVEN_RANGE */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flFormatFS(ioreq) formatCall(FL_FORMAT_FS,ioreq) +#endif /*flFormatFS*/ + +#ifndef flCreateLogicalPartitions +/*----------------------------------------------------------------------*/ +/* */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irCount : Number of LogicalPartitionParams structures */ +/* irData : Address of array of LogicalPartitionParams structures */ +/* irFlags : 0 - reserved */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flCreateLogicalPartitions(ioreq) formatCall(FL_CREATE_LOGICAL_PARTITIONS,ioreq) +#endif /*flCreateLogicalPartitions*/ + +#ifndef flFindLogicalPartition +/*----------------------------------------------------------------------*/ +/* */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (0, 1, ...) */ +/* bits 11-8 - Logical partition in Flash */ +/* partition (zero based) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irFlags : 0 - reserved */ +/* irData : Address of the LogPartitionInfo structure */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flFindLogicalPartition(ioreq) formatCall(FL_FIND_LOGICAL_PARTITION,ioreq) +#endif /* flFindLogicalPartition */ +#ifdef FL_SLPP +/*SLPP Specific*/ +/*----------------------------------------------------------------------*/ +/* f l D O C H S L P P U n l o c k R a n g e */ +/* */ +/* Unlock a range of sectors on a sector protected partition. */ +/* */ +/* Parameters: */ +/* irHandle : bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irData : Address of the DOCH_SLPPRangeRequestSector */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_SLPP_UNLOCK_RANGE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHSLPPUnlockRange(ioreq) bdCallDOCH(SDK_SLPP_UNLOCK_RANGE, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H S L P P L o c k R a n g e */ +/* */ +/* Lock a range of sectors on a sector protected partition. */ +/* */ +/* Parameters: */ +/* irHandle : bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irData : Address of the DOCH_SLPPRangeRequestSector */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_SLPP_LOCK_RANGE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHSLPPLockRange(ioreq) bdCallDOCH(SDK_SLPP_LOCK_RANGE, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H S L P P U n l o c k E n t i r e P a r t i t i o n */ +/* */ +/* Unlock an entire Sector Protected Partition. */ +/* */ +/* Parameters: */ +/* irHandle : bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_SLPP_UNLOCK_ENTIRE_PARTITION */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHSLPPUnlockEntirePartition(ioreq) bdCallDOCH(SDK_SLPP_UNLOCK_ENTIRE_PARTITION, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H S L P P S t i c k y L o c k R a n g e */ +/* */ +/* Applies sticky lock to a range of sectors on a sector protected */ +/* partition. */ +/* */ +/* Parameters: */ +/* irHandle : bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irData : Address of the DOCH_SLPPRangeRequestSector */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_SLPP_STICKY_LOCK_RANGE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHSLPPStickyLockRange(ioreq) bdCallDOCH(SDK_SLPP_STICKY_LOCK_RANGE, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H S L P P R e p o r t R a n g e s */ +/* */ +/* Reports unlocked and sticky locked ranges of sector protected */ +/* partition. */ +/* */ +/* Parameters: */ +/* irHandle : bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irData : Address of the DOCH_SLPPReport */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_SLPP_REPORT_LOCKED_RANGES */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHSLPPReportRanges(ioreq) bdCallDOCH(SDK_SLPP_REPORT_LOCKED_RANGES, ioreq) +#endif /*FL_SLPP*/ + +#ifdef __cplusplus +extern "C" { +#endif +/*Pass-Thru routine*/ +DOCH_Error DOCHAtaPassThrough(FLSNative socketNum, + FLSNative passThruOP, + DOCH_Registers *in_regs, + DOCH_Registers *out_regs, + FLNative secNum, + void* userBuff, + FLBoolean useInterrupt); + + +DOCH_Error DOCHIdentifyDiskOnChipDeviceSingleFloor(IOreq* ioreq); + +/*Flags for format operation*/ +#define DOCH_LEAVE_PARTITIONS 0x8 + + +#ifdef __cplusplus +} +#endif + +#endif /*_DOCHAPI*/ + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/doch_api.h linux-2.6.30.4/drivers/block/tffs/doch_api.h --- linux-2.6.30.4-orig/drivers/block/tffs/doch_api.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/doch_api.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,130 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/***********************************************************************************/ +/* */ +/* Header file for doch_api module */ +/* */ +/***********************************************************************************/ + +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Test for 7.x/src/H3/doch_api.h-arc $ + * + * Rev 1.32 Oct 22 2007 11:34:48 einat.avidan + * update copyrights header + * + * Rev 1.31 Sep 11 2006 13:45:14 yaniv.iarovici + * Legal header added + * + * Rev 1.30 Aug 09 2006 17:26:52 Polina.Marimont + * initial for DOC Driver 1.0 + * + */ + +#ifndef _DOCH_API +#define _DOCH_API + +#include "flcommon.h" +#include "flchkdef.h" +#include "_dochapi.h" +#include "blockdev.h" + + +/************************/ +/* Exported routines */ +/************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +extern FLBoolean gDochIrqEnabled[]; + +DOCH_Error bdCallDOCH(int functionNo, IOreq *ioreq); +extern DOCH_Error doch_init_socket (int socketNo, DOCH_InitSocket); +extern DOCH_Error doch_release_socket( int socketNo ); + +extern FLDword gDochAccessNanosec; + + +/*----------------------------------------------------------------------*/ +/* f l B u i l d G e o m e t r y */ +/* */ +/* Get C/H/S information of the disk according to number of sectors. */ +/* */ +/* Parameters: */ +/* capacity : Number of Sectors in Volume */ +/* cylinders : Pointer to Number of Cylinders */ +/* heads : Pointer to Number of Heads */ +/* sectors : Pointer to Number of Sectors per Track */ +/* oldFormat : True for one sector per culoster */ +/* wIrHandle : Handle of the disk partition to check */ +/* */ +/*----------------------------------------------------------------------*/ +TFFS_DLL_API void NAMING_CONVENTION flBuildGeometry(FLDword capacity, FLDword FAR2 *cylinders, + FLDword FAR2 *heads, FLDword FAR2 *sectors, FLBoolean oldFormat, FLWord wIrHandle); + +/* Management routines */ +DOCH_Error flDOCHAtaReset(FLByte socketNum); +DOCH_Error DochSDKInit(void); +void DochSDKExit(void); +DOCH_Error DochRegisterSocket(FLDword dwAddress); + +/* User define component registration routine */ +DOCH_Error flRegisterDochComponents(void); +/* Access layer registration routines */ +DOCH_Error hal_init_nor (FLSNative socketNo); +DOCH_Error hal_init_spi (FLSNative socketNo); +DOCH_Error hal_init_sim (FLSNative socketNo); +DOCH_Error hal_init_nor_noFunc (FLSNative socketNo); +DOCH_Error hal_init_spi_noFunc (FLSNative socketNo); +DOCH_Error hal_init_sim_noFunc (FLSNative socketNo); +DOCH_Error hal_init_user_routines(FLSNative socketNo, DOCH_BusAccess_routines accessPointerStruct); + +void DOCH_SetBits(FLDword* var, FLDword mask, FLByte offset, FLDword val); + +#ifdef __cplusplus +} +#endif + +#endif /*_DOCH_API*/ + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/doch_ata.c linux-2.6.30.4/drivers/block/tffs/doch_ata.c --- linux-2.6.30.4-orig/drivers/block/tffs/doch_ata.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/doch_ata.c 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,3627 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Test for 7.x/src/H3/doch_ata.c-arc $ + * + * Rev 1.80 Mar 09 2008 17:17:44 Yuli.Izrailov + * Changed doch_init_floors() flow to suit the mount time on both floors + * + * Rev 1.79 Feb 03 2008 13:46:22 Yuli.Izrailov + * Added Quick Init support. + * Bug fix: doch_check_chipID() - was not return with error on unknown Chip ID. + * + * Rev 1.77 Dec 26 2007 10:13:16 einat.avidan + * io_input() - after data XFER - make sure DRQ is off. + * fixed sequences for init and recoverFromPowerLoss. + * removed DOCH_CHECK_CHIP_ID flag (always check chip ID) + * + * Rev 1.76 Dec 16 2007 11:36:02 einat.avidan + * add debug printout + * + * Rev 1.75 Dec 11 2007 12:28:34 einat.avidan + * init sequence and DOCHConfigHW: change parameters of internal functions + * remove obsolete code (function doch_status) + * + * Rev 1.74 Dec 04 2007 17:27:14 einat.avidan + * Add readiness check before io_x sequences. + * Avoid writing to the same register more than once in short time + * Bug fix: DOCHBLK_READ and DOCHBLK_WRITE do not return value. + * Wait for mount before reset during init sequence + * Bug fix: part of configuration registers should be set only after device selection + * def_dochDelayUsec - receives new parameter: access time. + * + * Rev 1.73 Nov 07 2007 19:18:56 einat.avidan + * fix compilation error in retrieveAndPrintAtaDebug + * + * Rev 1.72 Oct 30 2007 17:01:26 einat.avidan + * replace dochEnableATAInterrupt function with macros + * bug fix: after write DMA transactions-waiting for ready + * was too long. + * + * Rev 1.71 Oct 23 2007 15:35:18 einat.avidan + * failure in reset in 128K window caused failure in init + * + * Rev 1.70 Oct 23 2007 12:27:52 einat.avidan + * optimization: delay after setting head register only + * when switching floors + * + * Rev 1.69 Oct 22 2007 11:34:48 einat.avidan + * update copyrights header + * + * Rev 1.68 Oct 21 2007 16:57:08 einat.avidan + * fix compilation warnings + * + * + * Rev 1.67 Oct 21 2007 10:39:56 Einat.Avidan + * optimization: save address of each Hib area instead of + * saving offset and core address (spare repetitive add commands) + * check return value of DOCH_SET_WINDOW_OFFSET + * fix printout and comments + * optimization:spare allocation of unnecessary local variabeles + * bug fix: cascaded configuration support in doch_init_socket + * make several trials to select second floor and read it's chip ID + * fix compilation warning + * + * Rev 1.66 Oct 11 2007 18:48:22 Einat.Avidan + * Replace global Boolean pattern with pattern in size of + * byte instead of dWord + * caller responsibility to set device head register + * when calling to doch_check_chipID + * fix printouts + * Interrupts are enabeled\ disabeled in the ATA level instead of API level + * remove unrequired ready check in io_output io_input and io_ctrl + * add long wait in delete partition command + * doch_reset resets both floor (no need of devNum parameter) + * Add support for reporting internal errors + * caller responsible to set device head register + * when calling to dochEnableATAInterrupt + * upport cascaded configuration: add delay after device switch + * add compilation flags for SOTP and SLPP + * + * Rev 1.65 Sep 04 2007 15:37:58 einat.avidan + * fix printouts + * bug fix: in io_output(): add_partition and secure_erase should + * have longer waiting time + * bug fix: in doch_init_socket(): no need to call flDOCHSetPowerMode + * twice for each floor + * + * Rev 1.64 Apr 05 2007 15:44:54 einat.avidan + * compilation warning fix (SCR 2765) + * + * Rev 1.63 Mar 13 2007 13:47:20 einat.avidan + * add support for SLPP + * + * Rev 1.62 Mar 12 2007 14:49:36 einat.avidan + * add compilation flag for disable SW reset + * + * Rev 1.61 Mar 11 2007 16:30:48 einat.avidan + * bug fix: check NULL pointers before using it + * + * Rev 1.60 Feb 28 2007 10:32:50 einat.avidan + * CX tools support + * + * Rev 1.59 Feb 15 2007 17:50:28 Einat.Avidan + * Enable burst without DMA + * bug fix in burst with DMA: sent the ATA command before it entered the burst mode. + * bug fix in burst with DMA:Did not allow DMA with edge + * Enables reading status asynchronous or synchronous in burst + * + * + * Rev 1.57.2.5 Dec 04 2006 12:44:40 Yaniv.Iarovici + * Add ; to MACRO + * + * Rev 1.57.2.4 Nov 30 2006 10:23:46 Yaniv.Iarovici + * Added DOCH_WAIT_B4_DEV1_ID (anchor for setting a delay between Dev0 and Dev1 ID process). + * + * Rev 1.57.2.3 Nov 21 2006 14:26:22 Yaniv.Iarovici + * 1. Typo in comments + * 2. Check ChipID before applying ATA reset. + * + * Rev 1.57.2.2 Nov 12 2006 09:46:52 Yaniv.Iarovici + * 1. Fixed compilation warnings. + * 2. doch_reset(): + * - Added parameter 'FLBoolean waitOnBusy'. + * - Wait for BUSY signal in ATA status register de-assertion before sending SRST, if waitOnBusy is TRUE. + * + * Rev 1.57.2.1 Oct 31 2006 12:23:32 yaniv.iarovici + * Added doch_init_window(). + * + * Rev 1.57.2.0 Oct 29 2006 11:28:54 Yaniv.Iarovici + * Fixed compilation warning. + * + * Rev 1.57 Oct 05 2006 11:00:36 yaniv.iarovici + * 1. Removed dwMulti_Read, dwMulti_Write. + * 2. Added dwMulti_MAX. + * + * Rev 1.56 Sep 14 2006 09:56:38 yaniv.iarovici + * Fix compilation warnings + * + * Rev 1.55 Sep 11 2006 13:45:14 yaniv.iarovici + * Legal header added + * + * Rev 1.54 Sep 10 2006 10:03:28 Yaniv.Iarovici + * Bug Fix: DMA handling in io_input() and io_output() (Device Head Register). + * + * Rev 1.53 Sep 03 2006 14:44:34 Yaniv.Iarovici + * Fixed DMA handling handling when DRQ>1. + * + * Rev 1.52 Aug 16 2006 08:45:46 Yaniv.Iarovici + * 1) Remove comment regarding #define DOCH_CHECK_CHIP_ID + * 2) Add global var: 'gIgnoreErrorBit' - used by ready() to ignore error bit when checking status (used when identifying device using ATA standard IDENTIFY DEVICE command) + * 3) Remove commented function - doch_pause() + * 4) Add 2nd argument 'FLSNative devNum' to doch_check_chipID() + * 5) Update clear_socket() to support 'ETFFS_Identified' field + * 6) Move the call to retrieveAndPrintAtaDebug() to after command is completed in doch_ata_passthru() + * 7) Add support to check CHIP ID on specific device (not only Dev0) in doch_check_chipID() + * 8) Add dunction 'doch_ATAstd_IDENTIFY_DEVICE(FLSNative socketNo, FLSNative devNum)' to identify a device using ATA standard IDENTIFY DEIVCE command when ETFFS was not detected on the device + * 9) Modify doch_init_socket() to: + * - Identify a device using ATA standard IDENTIFY DEVICE command when no ETFFS detected. + * - Check CHIP ID on specific device to reduce the time needed to identify NON-existing device. + * - Set Power Mode only if ETFFS was detected on the device. + * + * Rev 1.51 Aug 10 2006 10:23:02 Polina.Marimont + * bug fix - identifying in 128K window failure + * + * Rev 1.50 Aug 09 2006 17:26:52 Polina.Marimont + * initial for DOC Driver 1.0 + * + */ + +/* + * includes + */ + +#include "flcustom.h" +#include "flsystem.h" +#include "flchkdef.h" +#include "flsystyp.h" +#include "flcommon.h" +#include "flsysfun.h" +#include "doch_func.h" +#include "doch_ata.h" +#include "hib.h" + +#ifdef FL_MIGRATION_VERSION +#include "docsys.h" +#endif /*FL_MIGRATION_VERSION*/ + +FLWord gMemWindowType = 0; +FLDword gDochMemWinSize = 0; + +FLWord gHibContRegAreaAddress = 0; +FLWord gHibDataPortAreaAddress = 0; +FLWord gHibConfigRegAreaAddress = 0; + +#ifdef CHECK_POWER_ON_EVERY_COMMAND +FLByte gDeviceTurnedOff = FALSE; +#endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + +/*For utilities. Make it possible to seek one dev only*/ +#ifdef FL_UTILS_QUICK_INIT +extern FLByte gDochQuickInit; +#endif /*FL_UTILS_QUICK_INIT*/ + +#ifdef DEBUG_TIMEOUT +extern FLDword SysTimerFrequency; +extern void GetInternalSysTimer(FLDword * ticksHigh, FLDword * ticksLow); +#endif /*DEBUG_TIMEOUT*/ + +/* + * types + */ + +/* + * Global Variables + */ + +#ifdef __cplusplus +extern "C" { +#endif + +FLDword gAccessLayerType = 0; + +FLByte gATANoTimeout = 0; + +FLDword gUseShortWaitOnBusy = 0; + +FLDword gIgnoreErrorBit = 0; + +FLDword gDochAccessNanosec = 0; + +#ifdef DOCH_DMA_CONFIG +FLByte gDMAChannelOpen = 0; +#endif /*DOCH_DMA_CONFIG*/ + +DOCH_DpdSettings gDpdSettings; + +/* all DOCH sockets */ +DOCH_Socket sockets [DOCH_MAX_SOCKETS]; + +#ifdef __cplusplus +} +#endif + +#define DISABLE_INTERRUPT(pdev) \ + pdev->device[pdev->bAtaDevNum].flags &= ~DOCH_FLAGSB_USE_INTERRUPT;\ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CONTROL_REG, DOCH_ATA_NIEN) + +#ifdef DOCH_FILE_SIMULATION +#define ENABLE_INTERRUPT(pdev) \ + if (gAccessLayerType != DOCH_AL_SIM)\ + {\ + pdev->device[pdev->bAtaDevNum].flags |= DOCH_FLAGSB_USE_INTERRUPT;\ + }\ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CONTROL_REG,0) +#else /*DOCH_FILE_SIMULATION*/ +#define ENABLE_INTERRUPT(pdev) \ + pdev->device[pdev->bAtaDevNum].flags |= DOCH_FLAGSB_USE_INTERRUPT;\ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CONTROL_REG,0) +#endif /*DOCH_FILE_SIMULATION*/ +/* + * static vars + */ +static DOCH_DeviceUserAttr devUserAttr; + +static DOCH_ConfigRegsValue configRegValue; +static DOCH_ConfigRegsSet configRegValueSet; + +static FLByte ataDBG[DOCH_SECTOR_SIZE]; + +static DOCH_DeviceInfo gDiskOnChipDeviceInfo; + + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * static routines + */ +static void clear_socket(DOCH_Socket * pdev); +static DOCH_Error ready(DOCH_Socket *pdev, FLSNative devNum, DOCH_Reg reg, FLByte mask, FLByte on_bits, FLDword millisec); +static DOCH_Error doch_find_base_address(FLSNative socketNo, FLDword Address); + +static DOCH_Error doch_check_chipID(FLSNative socketNo); + +/* + * Internal routines + */ +DOCH_Error io_input(DOCH_Socket *pdev, FLSNative devNum, DOCH_Registers* regs, void *buf, FLNative secNum); +DOCH_Error io_output(DOCH_Socket *pdev, FLSNative devNum, DOCH_Registers* regs, void *buf, FLNative secNum); +DOCH_Error io_ctrl(DOCH_Socket *pdev, FLSNative devNum, DOCH_Registers* regs); + +/* + * externals + */ + +DOCH_Error get_out_registers(DOCH_Socket* pdev, FLSNative devNum, DOCH_Registers* out_regs); + +extern DOCH_Error flUnRegisterDochParams(FLSNative socketNo); + +extern FLByte gSdkDOCAddressObtained; +extern FLDword gConfigHWDefaults[DOCH_NUM_OF_DCONFIGHW_ITEMS]; + +extern FLByte gDochAtaDebug; + +extern FLByte gSdkInitDone; + + +#ifdef CX_ATA_SNIFFER +typedef struct _AtaCmdRec_S +{ + FLSNative socketNo; + FLByte bAtaCmdType; + FLSNative dwDevNum; + DOCH_Registers regs; + FLSNative dwSecNum; + +}AtaCmdRec_S; + +typedef enum _AtaCmdType +{ + CX_ATATYPE_CTRL=0x0, + CX_ATATYPE_INPUT=0x1, + CX_ATATYPE_OUTPUT=0x2 +}AtaCmdType; + +static AtaCmdRec_S ataCmdRec; +#endif /*CX_ATA_SNIFFER*/ + + +/****************************************************************************** + * * + * c l e a r _ s o c k e t * + * * + * Clears socket structure * + * * + * Parameters : * + * pdev : device to act on * + * * + ******************************************************************************/ +static +void clear_socket ( DOCH_Socket * pdev ) +{ + register FLSNative i = 0; + + pdev->wSocketNo = 0; + pdev->wNumOfDevices = 0; + pdev->nTotalCapacity = 0; + pdev->wTotalNumOfPartitions = 0; + pdev->wLastPartitionSpanned = 0; + pdev->bUseDMA = 0; + pdev->bUseInterrupt = 0; + pdev->bUseBurst = 0; + pdev->bAtaDevNum = 0; + pdev->bRegBase = NULL; +#ifdef DOCH_NO_SUPPORT_PARALLEL_SDK_INSTANCES + pdev->bLastDevNum = 0xFF; +#endif /*DOCH_NO_SUPPORT_PARALLEL_SDK_INSTANCES*/ + + for(i = 0; idevice[i].wNumOfPartitions = 0; + + pdev->device[i].ETFFS_Identified = FALSE; + + /* we assume that multiple sector read/writes aren't supported */ + pdev->device[i].dwMulti_MAX = 0; + pdev->device[i].dataTransferMode = DOCH_DATA_MODE_SINGLE; + + pdev->device[i].dwSpare1 = 0; + + } +} + +#ifdef CHECK_POWER_ON_EVERY_COMMAND +/****************************************************************************** + * * + * d o c h C h e c k P F S y m p t o m * + * * + * Wait until particular bit pattern appears in specified DOCH register * + * * + * Parameters : * + * pdev : device to act on * + * reg : DOCH register offset from base address * + * mask : bits we are interested in * + * on_bits : bits we are waiting to become '1' * + * millisec : timeout value in milliseconds * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ +DOCH_Error dochCheckPFSymptom(FLSNative socketNo, FLByte devNum, FLBoolean beforeCommand /* Used for debug prints */) +{ + DOCH_Error rc; + DOCH_Socket* pdev = NULL; + DOCH_Registers in_regs; + FLByte resetOccured = 0; + + if(!gSdkInitDone) + return DOCH_OK; + + /* Sanity Check*/ + /*=============*/ + if(socketNo > DOCH_MAX_SOCKETS - 1) + return DOCH_BadParameter; + + pdev = &sockets[socketNo]; + + /*Set Device Head register to appropriate device*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, DOCH_SELECT_DEV(devNum)); + DOCH_DELAY_AFTER_DEVICE_SWITCH(pdev,devNum); + + /*Check ChipID to detect power failure ("Device Off") */ + if(doch_check_chipID(socketNo) == DOCH_OK) /*caller responsibility to set device head register*/ + { + return DOCH_OK; + } + + /* Check reset status + Note: We DO NOT call DOCHGetResetStatus() to avoid recursion */ + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_GET_RESET_STATUS; + in_regs.bSectorCount = 0; + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_SELECT_DEV(devNum); + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + + gUseShortWaitOnBusy = DOCH_LONG_IDENTIFY_TIMEOUT; + rc = io_ctrl (pdev, devNum, &in_regs); + gUseShortWaitOnBusy = 0; + + resetOccured = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_SECTOR_CNT_REG); + + if(rc != DOCH_OK) + { + if(beforeCommand) + DBG_PRINT_ERR(FLZONE_ATA, "\r\ndochCheckPFSymptom(): io_ctrl DOCHGetResetStatus FAILED (Before Command)\r\n"); + else + DBG_PRINT_ERR(FLZONE_ATA, "\r\ndochCheckPFSymptom(): io_ctrl DOCHGetResetStatus FAILED (After Command)\r\n"); + + gDeviceTurnedOff = DOCH_GLOBAL_BOOL_PATTERN; + return DOCH_DeviceTurnedOff; + } + else if(resetOccured) + { + if(beforeCommand) + DBG_PRINT_ERR(FLZONE_ATA, "\r\ndochCheckPFSymptom(): Suspend mode detected (Before Command)\r\n"); + else + DBG_PRINT_ERR(FLZONE_ATA, "\r\ndochCheckPFSymptom(): Suspend mode detected (After Command)\r\n"); + + gDeviceTurnedOff = DOCH_GLOBAL_BOOL_PATTERN; + return DOCH_DeviceTurnedOff; + } + + else + { + if(beforeCommand) + DBG_PRINT_ERR(FLZONE_ATA, "\r\ndochCheckPFSymptom(): Suspend mode not detected but failed to read chip id (Before Command)\r\n"); + else + DBG_PRINT_ERR(FLZONE_ATA, "\r\ndochCheckPFSymptom(): Suspend mode not detected but failed to read chip id (After Command)\r\n"); + + gDeviceTurnedOff = DOCH_GLOBAL_BOOL_PATTERN; + return DOCH_DeviceTurnedOff; + } +} +#endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + +/****************************************************************************** + * * + * r e a d y * + * * + * Wait until particular bit pattern appears in specified DOCH register * + * * + * Parameters : * + * pdev : device to act on * + * reg : DOCH register offset from base address * + * mask : bits we are interested in * + * on_bits : bits we are waiting to become '1' * + * millisec : timeout value in milliseconds * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ +static +DOCH_Error ready ( DOCH_Socket * pdev, + FLSNative devNum, + DOCH_Reg reg, + FLByte mask, + FLByte on_bits, + FLDword millisec ) +{ + DOCH_Error error = DOCH_OK; + register FLDword tries; + FLByte status = 0; + + FLDword use_interrupt = + ( ((pdev->device[devNum].flags & DOCH_FLAGSB_USE_INTERRUPT) == DOCH_FLAGSB_USE_INTERRUPT) && + (pdev->bUseInterrupt) ); + +#ifdef DEBUG_TIMEOUT + FLDword dwTimeAfterHigh,dwTimeAfterLow,dwTimeBeforeHigh,dwTimeBeforeLow; + GetInternalSysTimer(&dwTimeBeforeHigh,&dwTimeBeforeLow); +#endif /*DEBUG_TIMEOUT*/ + + + /*Special case: ignore error bit + (should be ignored when performing ATA standard IDENTIFY DEVICE command)*/ + if(gIgnoreErrorBit) + mask &= ~(DOCH_ERROR); + + /*Protect against access time set to 0*/ + if(gDochAccessNanosec == 0) + { + DBG_PRINT_ERR(FLZONE_ATA, "ready(): Bad Parameter "); + return DOCH_BadParameter; + } + tries = millisec * (1000000UL / gDochAccessNanosec); + + /*If popper environment variable was set - set timeout to max*/ + if(gATANoTimeout == DOCH_GLOBAL_BOOL_PATTERN) + { + tries = DOCH_ATA_MAX_TIMEOUT; + } + + /*If gUseShortWaitOnBusy is set, use its value*/ + if(gUseShortWaitOnBusy != 0) + { + tries = gUseShortWaitOnBusy; + } + + /*Protect tries from being set to "0" + (in conjunction with tries-- might cause a very long delay...)*/ + if(tries == 0) + tries = 1; + + /*Wait for BUSY bit to clear*/ + while (tries-- > 0) + { + if ((millisec >= DOCH_LONG_WAIT) && (use_interrupt)) + { + /* wait for device's interrupt */ + DOCH_SLEEP(pdev->wSocketNo, devNum, DOCH_DEFAULT_SLEEP_PERIOD); + } + + status = DOCHREAD_ATA_REG(pdev->bRegBase, reg); + if ((status & mask) == on_bits) + { + /* read status once again, just to be sure .. */ + /*if ((DOCHREAD_ATA_REG(pdev->device[devNum].bRegBase, reg) & mask) == on_bits)*/ + return DOCH_OK; + } + /*If an error was detected - return the error code*/ + else if( ((status & DOCH_ERROR) == DOCH_ERROR) && + ((status & DOCH_BUSY) != DOCH_BUSY)) + { + error = (DOCH_Error)DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_ERROR_REG); + + /*Special Case - Device returned "0" in the error register. + This DOES NOT mean that everything is OK, since the error bit was raised. + Hence, we will return "DOCH_ATA_ERROR_ABORT"*/ + if(error == DOCH_OK) + error = DOCH_ATA_ERROR_ABORT; + + if(pdev->bUseInterrupt && (millisec == DOCH_SHORT_WAIT)) + { + DOCH_UNSERVICED_INTERRUPT(pdev->wSocketNo, devNum); + } + + DBG_PRINT_ERR(FLZONE_ATA, "ready(): ATA Error: "); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("0x%x status:0x%x device number:%d"),error,status,devNum)); + DBG_PRINT_ERR(FLZONE_ATA, "\r\n"); + + return error; + } + } + +#ifdef DEBUG_TIMEOUT + GetInternalSysTimer(&dwTimeAfterHigh,&dwTimeAfterLow); +#endif /*DEBUG_TIMEOUT*/ + + DBG_PRINT_ERR(FLZONE_ATA, "\r\nready(): Timed Out\r\n"); +#ifdef DEBUG_TIMEOUT + { + FLDword diffHigh,diffLow,dwWaitingTime; + FLDword scaledFreq= SysTimerFrequency/1000; /*mSec*/ + + diffHigh=(dwTimeAfterHigh-dwTimeBeforeHigh); + if(dwTimeAfterLow>=dwTimeBeforeLow) + { + diffLow= dwTimeAfterLow-dwTimeBeforeLow; + } + else + { + if (!diffHigh) + { + DBG_PRINT_ERR(FLZONE_ATA,"\nticks difference is negative\n"); + } + diffLow= 0xFFFFFFFFl- dwTimeBeforeLow + dwTimeAfterLow; + diffHigh --; + } + dwWaitingTime = (FLSDword)( (((0xFFFFFFFFl)/(scaledFreq)))*(diffHigh))+ + (((0xFFFFFFFFl)%(scaledFreq))*(diffHigh+1) + (diffLow))/(scaledFreq); + + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("\nTicks when started:high %lu low %lu"),dwTimeBeforeHigh,dwTimeBeforeLow)); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("\nTicks when timeout:high %lu low %lu"),dwTimeAfterHigh,dwTimeAfterLow)); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("\nTicks diff: high %d low %d"),diffHigh,diffLow)); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("\nDetected frequency %lu"), SysTimerFrequency)); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("\nWaiting time %d msec"), dwWaitingTime)); + + } +#endif /*DEBUG_TIMEOUT*/ + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("\r\ndevice number:%d status register: 0x%x, mask 0x%x, on_bits 0x%x\r\n"),devNum,status,mask,on_bits)); + + /*recalculate the number of tries for printout*/ + tries = millisec * (1000000UL / gDochAccessNanosec); + if(gATANoTimeout == DOCH_GLOBAL_BOOL_PATTERN) + { + tries = DOCH_ATA_MAX_TIMEOUT; + } + if(gUseShortWaitOnBusy != 0) + { + tries = gUseShortWaitOnBusy; + } + + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("\r\ntries %d ,millisec: %d, gATANoTimeout %d, gUseShortWaitOnBusy %d \r\n"),tries,millisec,gATANoTimeout,gUseShortWaitOnBusy)); + + /* If timeout had occurred, and not whilst looking for a device, + reset ATA and poll for ready */ + if(gUseShortWaitOnBusy == 0) + { + DBG_PRINT_ERR(FLZONE_ATA, "ready(): Resetting device... "); + error = doch_reset(pdev);/*reset both floors*/ + if(error == DOCH_OK) + DBG_PRINT_ERR(FLZONE_ATA, "Passed! \r\n"); + else + { + DBG_PRINT_ERR(FLZONE_ATA, "Failed! \r\n"); + return error; + } + } + + return DOCH_TimedOut; +} + +/****************************************************************************** + * * + * i o _ i n p u t * + * * + * Read sectors from DOCH device. * + * * + * Parameters : * + * pdev : device to act on * + * regs : DOCH_Registers * + * buf : user buffer to read to * + * secNum : # of sectors to read * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ +DOCH_Error io_input ( DOCH_Socket * pdev, + FLSNative devNum, + DOCH_Registers * regs, + void * buf, + FLNative secNum) +{ + FLNative sectors_to_read; + DOCH_Error rc; + FLSNative status; + +#ifdef CX_ATA_SNIFFER + extern FILE * ataLogFile; + ataCmdRec.bAtaCmdType = CX_ATATYPE_INPUT; + ataCmdRec.dwDevNum=devNum; + ataCmdRec.regs=*regs; + ataCmdRec.dwSecNum=(secNum ? secNum : 256); + if (!fwrite(&ataCmdRec,sizeof(AtaCmdRec_S),1,ataLogFile)) + { + DBG_PRINT_ERR(FLZONE_ATA, "\r\nError:io_input():Cannot write command rec to file \r\n"); + return DOCH_ATA_ERROR_ABORT; + } + if (fseek(ataLogFile,ataCmdRec.dwSecNum*DOCH_SECTOR_SIZE,SEEK_CUR )) + { DBG_PRINT_ERR(FLZONE_ATA, "\r\nError:io_input():Cannot fseek file error. \r\n"); + return DOCH_ATA_ERROR_ABORT; + } + fflush(ataLogFile); +#endif /*CX_ATA_SNIFFER*/ + + /*general sequence: + 1. set drive head register + 2. handle interrupts + 3. write ATA registers (if not DMA) + + 4. if BURST transfer:(Synchronous) + 4.1 set DOCH BURST READ Control Register + 4.2 if reading status sync - enter BURST mode on host + 4.3 initiate ATA Command + 4.4 for each buffer (in size of drqSize): + 4.4.1 Check DRQ ready and not BSY before data xfer + 4.4.2 if reading status async - enter BURST Mode on host + 4.4.3 Perform Read using burst + 4.4.4 if reading status async - exit BURST Mode on host + 4.5 if reading status sync - Exit BURST Mode on host + 4.6 Set DOCH BURST READ Control Register + + 5. else if DMA transfer: + 5.1 calculate number of blocks and start sector + 5.2 Set up the DMA transfer - Platfrom + 5.3 set device head register + 5.5 if burst mode required- Set DOCH BURST READ Control Register + 5.5 Set up the DMA transfer - Device (write DMA ctrl register) + 5.6 write ATA registers + 5.7 if burst mode required- enter BURST Mode + 5.8 Initiate ATA Command + 5.9 Wait for DMA transfer to complete + 5.10 if burst mode required-Exit BURST Mode + 5.11 Disable DMA + 5.12 Check status of DMA operation + 5.13 If DRQ>1 and some sectors are left to be transfered + perform another DMA transaction with altered frame/block sizes + + 6. else (PIO transfer): + 6.1 Initiate ATA Command + 6.2 Check DRQ ready and not BSY before data xfer + 6.3 for each buffer (in size of drqSize): + 6.3.1 read block + 6.3.2 Check DRQ ready (don`t perform after LAST sector was transfered) + + 7. wait until device is ready + 8. check operation's status + */ + + + /*Calculate how many sectors are to be read*/ + /*Note: "0" - 256 Sectors to read*/ + sectors_to_read = (secNum ? secNum : 256); + + /* 1. set drive head register*/ + /*****************************/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, regs->bDriveHead); + DOCH_DELAY_AFTER_DEVICE_SWITCH(pdev,((regs->bDriveHead & DOCH_DEVICE) == DOCH_DEVICE)); + + /* 2. handle interrupts*/ + /***********************/ + /*enable interrupt - caller responsibility to set floor*/ + if (pdev->bUseInterrupt && DOCH_IRQ_RB_INIT(pdev->wSocketNo)) + { + ENABLE_INTERRUPT(pdev); + } + + /*Wait for busy bit to clear*/ + status = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_STATUS_REG); + if((status & (DOCH_BUSY|DOCH_DRQ|DOCH_READY))!= DOCH_READY) + { + if ((rc = ready(pdev, devNum, DOCH_ALT_STATUS_REG, (DOCH_BUSY|DOCH_DRQ|DOCH_READY), DOCH_READY, DOCH_SHORT_WAIT)) != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_input(): ATA not Ready (before command) \r\n"); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x \r\n"),rc)); + DISABLE_INTERRUPT(pdev); + return rc; + } + } + + /*3. write ATA registers (if not DMA)*/ + /*************************************/ + /*Write ATA registers, without ATA command register*/ + /*Note: if DMA was requested, registers will be written inside DMA context*/ + if(!pdev->bUseDMA) + { + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_CNT_REG, regs->bSectorCount); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_NO_REG, regs->bSectorNumber); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CYLINDER_LOW_REG, regs->bCylLow); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CYLINDER_HIGH_REG, regs->bCylHigh); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_FEATURES_REG, regs->bFeaturesError); + } + + /*******************BURST transfer was requested************************/ + /*4. if BURST transfer:(Synchronous) */ + /*************************************/ + #ifdef DOCH_USE_BURST_MODE_READ + if((pdev->bUseBurst) && (!pdev->bUseDMA)) + { + FLByte drqSize = 0; + FLByte i; + + if(pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_SINGLE) + { + drqSize = 1; + } + else if(pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_MULT) + { + drqSize = (FLByte)pdev->device[devNum].dwMulti_Current; + } + + /*4.1 set DOCH BURST READ Control Register*/ + /******************************************/ + DOCHWRITE_CTRL_REG (pdev->bRegBase, + HIB_BURST_READ_MODE_CTRL_REG, + (DOCH_BURST_ENABLE | DOCH_BURST_HOLD | DOCH_BURST_LENGTH | (DOCH_BURST_LATENCY) | (DOCH_BURST_WAIT_STATE)) + ); + +#ifndef DOCH_READ_STATUS_ASYNC_IN_BURST + /*4.2 if reading status sync - enter BURST mode on host*/ + /******************************************************/ + DOCH_HOST_ENTER_READ_BURST_MODE; +#endif /*DOCH_READ_STATUS_ASYNC_IN_BURST*/ + + /*4.3 initiate ATA Command*/ + /**************************/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_COMMAND_REG, regs->bCommandStatus); + + /*4.4 for each buffer (in size of drqSize):*/ + /*******************************************/ + for(i=0; ibRegBase, + DOCH_DATA_PORT_AREA_ADDRESS, + (FLByte*)buf + (i<bRegBase, HIB_BURST_READ_MODE_CTRL_REG , DOCH_BURST_DISABLE); + } + else + #endif /*DOCH_USE_BURST_MODE_READ*/ + + /******************* DMA transfer was requested ************************/ + /*5. else if DMA transfer:*/ + /**************************/ + #ifdef DOCH_DMA_CONFIG + if(pdev->bUseDMA) + { + DMA_Params_S dmaParams; + FLDword dmaFirstReqSector, + dmaFirstSectorToPerform, + dmaRemainderSectors, + dmaRemainderOffset, + dmaBlocks, + dmaFrameSize; + FLWord wDmaRegValue = DOCHREAD_CTRL_REG (pdev->bRegBase, HIB_DMA_CTRL_REG); + + /*5.1 calculate number of blocks and start sector*/ + /*************************************************/ + /*Initial Value*/ + dmaRemainderOffset = 0; + + /*Save the first sector position*/ + dmaFirstReqSector = (regs->bSectorNumber + + (regs->bCylLow<<8) + + (regs->bCylHigh<<16)+ + ((regs->bDriveHead & 0xF)<<24)); + + dmaFirstSectorToPerform = dmaFirstReqSector; + + if(pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_SINGLE) + { + dmaRemainderSectors = 0; + dmaFrameSize = 1; + dmaBlocks = sectors_to_read; + } + else if (pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_MULT) + { + dmaRemainderSectors = (sectors_to_read % pdev->device[devNum].dwMulti_Current); + + /*Set initial parameters (will be altered afterwards to transfer "remainder" sectors*/ + dmaBlocks = (sectors_to_read / pdev->device[devNum].dwMulti_Current); + dmaFrameSize = pdev->device[devNum].dwMulti_Current; + } + else + { + DBG_PRINT_ERR(FLZONE_ATA, "io_input(): DMA Transfer Mode "); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("0x%x "), pdev->device[devNum].dataTransferMode)); + DBG_PRINT_ERR(FLZONE_ATA, "not supported\r\n"); + DISABLE_INTERRUPT(pdev); + return DOCH_FeatureNotSupported; + } /* End of if/else on pdev->device[devNum].dataTransferMode */ + +dochIoInputDmaSequence: + if(dmaBlocks > 0) + { + /*5.2 Set up the DMA transfer - Platfrom*/ + /****************************************/ + dmaParams.bOpType = DOCH_DMA_CONFIG_TRANSACTION_DEVICE_TO_HOST; + + dmaParams.bDiskOnChip_BasePtr = (FLByte*)pdev->bRegBase; + dmaParams.wDiskOnChip_Offset = (FLWord)DOCH_DATA_PORT_AREA; + dmaParams.bDestAddrPtr = (FLByte*)buf + dmaRemainderOffset; + + dmaParams.wFrameSize = (FLWord)(dmaFrameSize * DOCH_SECTOR_SIZE); + dmaParams.wFramesInBlock = (FLWord)(dmaBlocks); + + dmaParams.wFramesXferred = 0; + + DOCH_DMA_CONFIG(&dmaParams); + if(dmaParams.fDmaStatus != 0) + { + DBG_PRINT_ERR(FLZONE_API, "io_input(): DOCH_DMA_CONFIG_TRANSACTION_DEVICE_TO_HOST Failed\r\n"); + DISABLE_INTERRUPT(pdev); + return DOCH_GeneralFailure; + } + + /*5.3 set device head register if needed*/ + /****************************************/ + if (dmaFirstSectorToPerform != dmaFirstReqSector) + { /* no need to update device head on first time*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, ((regs->bDriveHead & 0xF0) | + ((FLByte)((dmaFirstSectorToPerform>>24) & 0x0F)))); + + } + + + #ifdef DOCH_USE_BURST_MODE_READ + /*5.4 if burst mode required- Set DOCH BURST READ Control Register*/ + /******************************************************************/ + if(pdev->bUseBurst) + { + /*Set DOCH BURST READ Control Register*/ + DOCHWRITE_CTRL_REG (pdev->bRegBase, + HIB_BURST_READ_MODE_CTRL_REG, + (DOCH_BURST_ENABLE | DOCH_BURST_HOLD | DOCH_BURST_LENGTH | DOCH_BURST_LATENCY | DOCH_BURST_WAIT_STATE) ); + } + #endif /*DOCH_USE_BURST_MODE_READ*/ + + /*5.5 Set up the DMA transfer - Device (write DMA ctrl register)*/ + /****************************************************************/ + DOCHWRITE_CTRL_REG (pdev->bRegBase, HIB_DMA_CTRL_REG, (wDmaRegValue | DOCH_DMA_REQ_ENABLE)); + + /*5.6 write ATA registers*/ + /*************************/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_CNT_REG, (FLByte)(dmaFrameSize*dmaBlocks)); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_NO_REG, (FLByte)(dmaFirstSectorToPerform)); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CYLINDER_LOW_REG, (FLByte)(dmaFirstSectorToPerform>>8)); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CYLINDER_HIGH_REG, (FLByte)(dmaFirstSectorToPerform>>16)); + /*DOCH_DELAY_AFTER_DEVICE_SWITCH; Actually this delay is unnecessary */ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_FEATURES_REG, regs->bFeaturesError); + + #ifdef DOCH_USE_BURST_MODE_READ + /*5.7 if burst mode required- enter BURST Mode*/ + /**********************************************/ + if(pdev->bUseBurst) + { + DOCH_HOST_ENTER_READ_BURST_MODE; + } + #endif /*DOCH_USE_BURST_MODE_READ*/ + + /*5.8 Initiate ATA Command*/ + /**************************/ + /*This will also start DMA transfer*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_COMMAND_REG, regs->bCommandStatus); + + /*5.9 Wait for DMA transfer to complete*/ + /***************************************/ + dmaParams.bOpType = DOCH_DMA_WAIT_FOR_READ_TRANSACTION_END; + DOCH_DMA_CONFIG(&dmaParams); + + #ifdef DOCH_USE_BURST_MODE_READ + /*5.10 if burst mode required-Exit BURST Mode*/ + /********************************************/ + if(pdev->bUseBurst) + { + DOCH_HOST_EXIT_READ_BURST_MODE; + + /*Set DOCH BURST READ Control Register*/ + DOCHWRITE_CTRL_REG (pdev->bRegBase, HIB_BURST_READ_MODE_CTRL_REG , DOCH_BURST_DISABLE); + } + #endif /*DOCH_USE_BURST_MODE_READ*/ + + /*5.11 Disable DMA*/ + /******************/ + DOCHWRITE_CTRL_REG (pdev->bRegBase, HIB_DMA_CTRL_REG, (wDmaRegValue &= ~DOCH_DMA_REQ_ENABLE)); + + /*5.12 Check status of DMA operation*/ + /************************************/ + if(dmaParams.fDmaStatus != 0) + { + DISABLE_INTERRUPT(pdev); + DBG_PRINT_ERR(FLZONE_API, "io_input(): DOCH_DMA_WAIT_FOR_READ_TRANSACTION_END Failed\r\n"); + DBG_PRINT_ERR_PRM(FLZONE_API,(FLTXT("dma status:%d frames xFererred:%d:%d\r\n"), + dmaParams.fDmaStatus,dmaParams.wFramesXferred)); + DBG_PRINT_ERR_PRM(FLZONE_API,(FLTXT("dmaParams:OpType:%d IrHandle:%d \r\n"), + dmaParams.bOpType,dmaParams.bIrHandle)); + DBG_PRINT_ERR_PRM(FLZONE_API,(FLTXT("dmaParams:frame size:%d Frames in block:%d\r\n"), + dmaParams.wFrameSize,dmaParams.wFramesInBlock)); + DBG_PRINT_ERR_PRM(FLZONE_API,(FLTXT("dmaParams:mDoc base:0x%x mDoc offset:0x%x dest address:0x%x \r\n"), + dmaParams.bDiskOnChip_BasePtr,dmaParams.wDiskOnChip_Offset,dmaParams.bDestAddrPtr)); + + DBG_PRINT_ERR(FLZONE_ATA, "io_input(): Resetting device... "); + rc = doch_reset(pdev);/*reset both floors*/ + if(rc == DOCH_OK) + DBG_PRINT_ERR(FLZONE_ATA, "Passed! \r\n"); + else + { + DBG_PRINT_ERR(FLZONE_ATA, "Failed! \r\n"); + DISABLE_INTERRUPT(pdev); + return rc; + } + return DOCH_GeneralFailure; + } + + } + + /*5.13 If DRQ>1 and some sectors are left to be transfered + *perform another DMA transaction with altered frame/block sizes*/ + /****************************************************************/ + if(dmaRemainderSectors > 0) + { + dmaRemainderOffset = (dmaBlocks * dmaFrameSize * DOCH_SECTOR_SIZE); + dmaFirstSectorToPerform = (dmaFirstReqSector + (dmaBlocks * dmaFrameSize)); + + dmaBlocks = 1; + dmaFrameSize = dmaRemainderSectors; + + dmaRemainderSectors = 0; + + goto dochIoInputDmaSequence; + } + + } + else + #endif /*DOCH_DMA_CONFIG*/ + + /*******************PIO transfer was requested************************/ + /*6. else (PIO transfer):*/ + /*************************/ + { + FLNative secPerformed; + FLNative offset = 0; + /*6.1 Initiate ATA Command*/ + /**************************/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_COMMAND_REG, regs->bCommandStatus); + + /*6.2 Check DRQ ready and not BSY before data xfer*/ + /**************************************************/ + (rc = ready(pdev, devNum, DOCH_STATUS_REG, (DOCH_READY | DOCH_DRQ | DOCH_BUSY | DOCH_ERROR), + DOCH_READY | DOCH_DRQ, DOCH_LONG_WAIT)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_input(): ATA not Ready (before data XFER) \r\n"); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x \r\n"),rc)); + DISABLE_INTERRUPT(pdev); + return rc; + } + + /*6.3 for each buffer (in size of drqSize):*/ + /*******************************************/ + if((pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_SINGLE) || /*Single Sector was requested*/ + (!(regs->bCommandStatus == DOCH_VSCMD_READ_PARTITION)) ) /*Command is OTHER than Read Partition*/ + { + for(secPerformed=1; secPerformed<=sectors_to_read; secPerformed++) + { + /*6.3.1 read block*/ + /******************/ + DOCHBLK_READ(pdev->bRegBase,((FLByte*)buf + offset),1); + + + /*6.3.2 Check DRQ ready and not BSY before next data xfer */ + /**********************************************************/ + /* (don`t perform after LAST sector was transfered) */ + if(secPerformed != sectors_to_read) + { + (rc = ready(pdev, devNum, DOCH_STATUS_REG, (DOCH_READY | DOCH_DRQ | DOCH_BUSY | DOCH_ERROR), + DOCH_READY | DOCH_DRQ, DOCH_LONG_WAIT)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_input(): ATA not Ready (after data XFER) \r\n"); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x , sector = %d \r\n"),rc,secPerformed)); + DISABLE_INTERRUPT(pdev); + return rc; + } + } + + offset += DOCH_SECTOR_SIZE; + } + + } + else if(pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_MULT) + { + FLByte multCount = (FLByte)pdev->device[devNum].dwMulti_Current; + FLByte multSecToRead = 0; + + for(secPerformed=0; secPerformed sectors_to_read) + multSecToRead = (sectors_to_read - secPerformed); + else + multSecToRead = multCount; + + /*Perform data xfer*/ + DOCHBLK_READ(pdev->bRegBase, (FLByte*)buf + offset,(multSecToRead)); + + /* Check DRQ ready and not BSY before next data xfer */ + /* (don`t perform after LAST sector was transfered) */ + if((secPerformed + multSecToRead) != sectors_to_read) + { + (rc = ready(pdev, devNum, DOCH_STATUS_REG, (DOCH_READY | DOCH_DRQ | DOCH_BUSY | DOCH_ERROR), + DOCH_READY | DOCH_DRQ, DOCH_LONG_WAIT)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_input(): ATA not Ready (after data XFER) \r\n"); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x, sector = %d \r\n"),rc, secPerformed)); + DISABLE_INTERRUPT(pdev); + return rc; + } + } + + /*Advance number of written sectors and update pointer to buffer*/ + secPerformed += multSecToRead; + offset += (multSecToRead * DOCH_SECTOR_SIZE); + } + } + else + { + DBG_PRINT_ERR(FLZONE_ATA, "io_input(): Transfer Mode "); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("0x%x "), pdev->device[devNum].dataTransferMode)); + DBG_PRINT_ERR(FLZONE_ATA, "not supported\r\n"); + DISABLE_INTERRUPT(pdev); + return DOCH_FeatureNotSupported; + + } /* End of if/else on pdev->device[devNum].dataTransferMode */ + + } /* End of else on if(pdev->bUseDMA) */ + + /*******************end of different transfer modes ************************/ + + /* 7. wait until device is ready */ + /*********************************/ + rc = ready(pdev, devNum, DOCH_STATUS_REG, (DOCH_READY | DOCH_BUSY|DOCH_DRQ), + DOCH_READY, DOCH_SHORT_WAIT); + if (rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_input(): ATA not Ready (after completion)\r\n"); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x \r\n"),rc)); + DISABLE_INTERRUPT(pdev); + return rc; + } + + /*8. check operation's status */ + /******************************/ + status = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_STATUS_REG); + if((status & (DOCH_BUSY | DOCH_READY | DOCH_ERROR)) != DOCH_READY) + { + DISABLE_INTERRUPT(pdev); + DBG_PRINT_ERR(FLZONE_ATA, "io_input(): after completion status register indicates a problem: "); + DBG_PRINT_ERR_PRM(FLZONE_ATA,(FLTXT("reported status 0x%x\r\n"),status)); + if((status & DOCH_ERROR) == DOCH_ERROR) + { + return DOCH_ATAErrorDetected; + } + return DOCH_ATANotReady; + + } + + DISABLE_INTERRUPT(pdev); +#ifdef CX_ATA_SNIFFER +{ + FLSDword i=0; + if (fseek(ataLogFile,-ataCmdRec.dwSecNum*DOCH_SECTOR_SIZE,SEEK_CUR )) + { DBG_PRINT_ERR(FLZONE_ATA, "\r\nError:io_input():Cannot fseek file error. \r\n"); + return DOCH_ATA_ERROR_ABORT; + } + for (i=0;ibCommandStatus!= DOCH_VSCMD_PARTITION_MANAGEMENT)? DOCH_LONG_WAIT:\ + ((regs->bFeaturesError ==DOCH_ADD_PARTITION || regs->bFeaturesError ==DOCH_SECURE_ERASE)? DOCH_VERY_LONG_WAIT:DOCH_LONG_WAIT)); +#ifdef CX_ATA_SNIFFER + extern FILE * ataLogFile; + ataCmdRec.bAtaCmdType = CX_ATATYPE_OUTPUT; + ataCmdRec.dwDevNum=devNum; + ataCmdRec.regs=*regs; + ataCmdRec.dwSecNum=(secNum ? secNum : 256); + if (!fwrite(&ataCmdRec,sizeof(AtaCmdRec_S),1,ataLogFile)) + { + DBG_PRINT_ERR(FLZONE_ATA, "\r\nError:io_output():Cannot write command rec to file \r\n"); + return DOCH_ATA_ERROR_ABORT; + } + + { + FLSDword i=0; + for (i=0;i1 and some sectors are left to be transfered + perform another DMA transaction with altered frame/block sizes + + 6. else (PIO transfer): + 6.1 Initiate ATA Command + 6.2 Check DRQ ready and not BSY before data xfer + 6.3 for each buffer (in size of drqSize): + 6.3.1 read block + 6.3.2 Check DRQ ready (don`t perform after LAST sector was transfered) + + 7. wait until device is ready + 8. check operation's status + */ + + + /*Calculate how many sectors are to be written*/ + /*Note: "0" - 256 Sectors to write*/ + sectors_to_write = (secNum ? secNum : 256); + + /* 1. set drive head register*/ + /*****************************/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, regs->bDriveHead); + DOCH_DELAY_AFTER_DEVICE_SWITCH(pdev,((regs->bDriveHead & DOCH_DEVICE) == DOCH_DEVICE)); + + /*2. handle interrupts*/ + /**********************/ + /*caller responsibility to set floor*/ + if (pdev->bUseInterrupt && DOCH_IRQ_RB_INIT(pdev->wSocketNo)) + { + ENABLE_INTERRUPT(pdev); + } + + /*Wait for BUSY bit to clear*/ + status = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_STATUS_REG); + if((status & (DOCH_READY|DOCH_BUSY|DOCH_DRQ))!= DOCH_READY) + { + if ((rc = ready(pdev, devNum, DOCH_ALT_STATUS_REG, (DOCH_READY|DOCH_BUSY|DOCH_DRQ), DOCH_READY, DOCH_SHORT_WAIT)) != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_output(): ATA not Ready (before command)\r\n"); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x \r\n"),rc)); + DISABLE_INTERRUPT(pdev); + return rc; + } + } + + /*3. write ATA registers (if not DMA)*/ + /*************************************/ + /*Write ATA registers, without ATA command register*/ + /*Note: if DMA was requested, registers will be written inside DMA context*/ + if(!pdev->bUseDMA) + { + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_CNT_REG, regs->bSectorCount); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_NO_REG, regs->bSectorNumber); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CYLINDER_LOW_REG, regs->bCylLow); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CYLINDER_HIGH_REG, regs->bCylHigh); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_FEATURES_REG, regs->bFeaturesError); + } + + /*******************BURST transfer was requested************************/ + /*4. if BURST transfer:(Synchronous) */ + /*************************************/ + #ifdef DOCH_USE_BURST_MODE_WRITE + if(pdev->bUseBurst) + { + FLByte drqSize = 0; + FLByte i; + + if(pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_SINGLE) + { + drqSize = 1; + } + else if(pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_MULT) + { + drqSize = (FLByte)pdev->device[devNum].dwMulti_Current; + } + + /*4.1 initiate ATA Command*/ + /**************************/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_COMMAND_REG, regs->bCommandStatus); + + /*4.2 set DOCH BURST WRITE Control Register*/ + /******************************************/ + DOCHWRITE_CTRL_REG (pdev->bRegBase, + HIB_BURST_WRITE_MODE_CTRL_REG, + (DOCH_BURST_ENABLE | DOCH_BURST_HOLD | DOCH_BURST_LENGTH | DOCH_BURST_LATENCY | DOCH_BURST_WAIT_STATE) + ); + /*4.3 if reading status sync - enter BURST mode on host*/ + /******************************************************/ + DOCH_HOST_ENTER_WRITE_BURST_MODE; + + /*4.4 for each buffer (in size of drqSize):*/ + /*******************************************/ + for(i=0; ibRegBase, + DOCH_DATA_PORT_AREA_ADDRESS, + (FLByte*)buf + (i<bRegBase, HIB_BURST_WRITE_MODE_CTRL_REG, DOCH_BURST_DISABLE); + + } + else + #endif /*DOCH_USE_BURST_MODE_WRITE*/ + /******************* DMA transfer was requested ************************/ + /*5. else if DMA transfer:*/ + /**************************/ + #ifdef DOCH_DMA_CONFIG + /*DMA transfer was requested*/ + if(pdev->bUseDMA) + { + DMA_Params_S dmaParams; + FLDword dmaFirstReqSector, + dmaFirstSectorToPerform, + dmaRemainderSectors, + dmaRemainderOffset, + dmaBlocks, + dmaFrameSize; + FLWord wDmaRegValue = DOCHREAD_CTRL_REG (pdev->bRegBase, HIB_DMA_CTRL_REG); + /*5.1 calculate number of blocks and start sector*/ + /*************************************************/ + /*Initial Value*/ + dmaRemainderOffset = 0; + + /*Save the first sector position*/ + dmaFirstReqSector = (regs->bSectorNumber + + (regs->bCylLow<<8) + + (regs->bCylHigh<<16)+ + ((regs->bDriveHead & 0xF)<<24)); + + dmaFirstSectorToPerform = dmaFirstReqSector; + + if(pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_SINGLE) + { + dmaRemainderSectors = 0; + dmaFrameSize = 1; + dmaBlocks = sectors_to_write; + } + else if (pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_MULT) + { + dmaRemainderSectors = (sectors_to_write % pdev->device[devNum].dwMulti_Current); + + /*Set initial parameters (will be altered afterwards to transfer "remainder" sectors*/ + dmaBlocks = (sectors_to_write / pdev->device[devNum].dwMulti_Current); + dmaFrameSize = pdev->device[devNum].dwMulti_Current; + } + else + { + DBG_PRINT_ERR(FLZONE_ATA, "io_output(): DMA Transfer Mode "); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("0x%x "), pdev->device[devNum].dataTransferMode)); + DBG_PRINT_ERR(FLZONE_ATA, "not supported\r\n"); + DISABLE_INTERRUPT(pdev); + return DOCH_FeatureNotSupported; + } /* End of if/else on pdev->device[devNum].dataTransferMode */ + +dochIoOutputDmaSequence: + if(dmaBlocks > 0) + { + /*5.2 Set up the DMA transfer - Platform*/ + /****************************************/ + dmaParams.bOpType = DOCH_DMA_CONFIG_TRANSACTION_HOST_TO_DEVICE; + + dmaParams.bDiskOnChip_BasePtr = ((FLByte*)pdev->bRegBase); + dmaParams.wDiskOnChip_Offset = DOCH_DATA_PORT_AREA; + dmaParams.bDestAddrPtr = (FLByte*)buf + dmaRemainderOffset; + + dmaParams.wFrameSize = (FLWord)(dmaFrameSize * DOCH_SECTOR_SIZE); + dmaParams.wFramesInBlock = (FLWord)(dmaBlocks); + + dmaParams.wFramesXferred = 0; + + DOCH_DMA_CONFIG(&dmaParams); + if(dmaParams.fDmaStatus != 0) + { + DBG_PRINT_ERR(FLZONE_API, "io_output(): DOCH_DMA_CONFIG_TRANSACTION_HOST_TO_DEVICE Failed\r\n"); + DISABLE_INTERRUPT(pdev); + return DOCH_GeneralFailure; + } + + /*5.3 set device head register if needed*/ + /****************************************/ + if (dmaFirstSectorToPerform!= dmaFirstReqSector) + { /* no need to update device head on first time*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, ((regs->bDriveHead & 0xF0) | + ((FLByte)((dmaFirstSectorToPerform>>24) & 0x0F)))); + + } + + /*5.4 Set up the DMA transfer - Device (write DMA ctrl register)*/ + /****************************************************************/ + DOCHWRITE_CTRL_REG (pdev->bRegBase, HIB_DMA_CTRL_REG, (wDmaRegValue | DOCH_DMA_REQ_ENABLE)); + + /*5.5 write ATA registers*/ + /*************************/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_CNT_REG, (FLByte)(dmaFrameSize*dmaBlocks)); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_NO_REG, (FLByte)(dmaFirstSectorToPerform)); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CYLINDER_LOW_REG, (FLByte)(dmaFirstSectorToPerform>>8)); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CYLINDER_HIGH_REG, (FLByte)(dmaFirstSectorToPerform>>16)); + /*DOCH_DELAY_AFTER_DEVICE_SWITCH; Actually this delay is unnecessary */ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_FEATURES_REG, regs->bFeaturesError); + + /*5.6 Initiate ATA Command*/ + /**************************/ + /*This will also start DMA transfer*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_COMMAND_REG, regs->bCommandStatus); + + /*5.7 Wait for DMA transfer to complete*/ + /***************************************/ + dmaParams.bOpType = DOCH_DMA_WAIT_FOR_WRITE_TRANSACTION_END; + DOCH_DMA_CONFIG(&dmaParams); + + /*5.8 Disable DMA*/ + /*****************/ + DOCHWRITE_CTRL_REG (pdev->bRegBase, HIB_DMA_CTRL_REG, (wDmaRegValue &= ~DOCH_DMA_REQ_ENABLE)); + + /*5.9 Check status of DMA operation*/ + /***********************************/ + if(dmaParams.fDmaStatus != 0) + { + DISABLE_INTERRUPT(pdev); + DBG_PRINT_ERR(FLZONE_API, "io_output(): DOCH_DMA_WAIT_FOR_WRITE_TRANSACTION_END Failed\r\n"); + DBG_PRINT_ERR_PRM(FLZONE_API,(FLTXT("dma status:%d frames xFererred:%d:%d\r\n"), + dmaParams.fDmaStatus,dmaParams.wFramesXferred)); + DBG_PRINT_ERR_PRM(FLZONE_API,(FLTXT("dmaParams:OpType:%d IrHandle:%d \r\n"), + dmaParams.bOpType,dmaParams.bIrHandle)); + DBG_PRINT_ERR_PRM(FLZONE_API,(FLTXT("dmaParams:frame size:%d Frames in block:%d\r\n"), + dmaParams.wFrameSize,dmaParams.wFramesInBlock)); + DBG_PRINT_ERR_PRM(FLZONE_API,(FLTXT("dmaParams:mDoc base:0x%x mDoc offset:0x%x dest address:0x%x \r\n"), + dmaParams.bDiskOnChip_BasePtr,dmaParams.wDiskOnChip_Offset,dmaParams.bDestAddrPtr)); + + DBG_PRINT_ERR(FLZONE_ATA, "io_outut(): Resetting device... "); + rc = doch_reset(pdev); + if(rc == DOCH_OK) + DBG_PRINT_ERR(FLZONE_ATA, "Passed! \r\n"); + else + { + DBG_PRINT_ERR(FLZONE_ATA, "Failed! \r\n"); + return rc; + } + + return DOCH_GeneralFailure; + } + + } + + /*5.10 If DRQ>1 and some sectors are left to be transfered + *perform another DMA transaction with altered frame/block sizes*/ + /****************************************************************/ + if(dmaRemainderSectors > 0) + { + dmaRemainderOffset = (dmaBlocks * dmaFrameSize * DOCH_SECTOR_SIZE); + dmaFirstSectorToPerform = (dmaFirstReqSector + (dmaBlocks * dmaFrameSize)); + + dmaBlocks = 1; + dmaFrameSize = dmaRemainderSectors; + + dmaRemainderSectors = 0; + + goto dochIoOutputDmaSequence; + } + + /*once DMA transation endded - device should be ready*/ + /* do not wait in that case long time*/ + dwLongWait = DOCH_SHORT_WAIT; + + } + else + #endif /*DOCH_DMA_CONFIG*/ + + /*******************PIO transfer was requested************************/ + /*6. else (PIO transfer):*/ + /*************************/ + { + /*6.1 Initiate ATA Command*/ + /**************************/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_COMMAND_REG, regs->bCommandStatus); + + /*6.2 Check DRQ ready and not BSY before data xfer*/ + /**************************************************/ + (rc = ready(pdev, devNum, DOCH_STATUS_REG, (DOCH_READY | DOCH_DRQ | DOCH_BUSY | DOCH_ERROR), + DOCH_READY | DOCH_DRQ, DOCH_SHORT_WAIT)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_output(): ATA not Ready (before data Xfer)\r\n"); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x \r\n"),rc)); + DISABLE_INTERRUPT(pdev); + return rc; + } + + /*6.3 for each buffer (in size of drqSize):*/ + /*******************************************/ + if((pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_SINGLE) || /*Single Sector was requested*/ + (!(regs->bCommandStatus == DOCH_VSCMD_WRITE_PARTITION)) ) /*Command is OTHER than Write Partition*/ + { + for(secPerformed=1; secPerformed<=sectors_to_write; secPerformed++) + { + /*6.3.1 write block*/ + /******************/ + DOCHBLK_WRITE(pdev->bRegBase, (FLByte*)buf + offset,1); + + + /*6.3.2 Check DRQ ready and not BSY before next data xfer */ + /**********************************************************/ + /* (don`t perform after LAST sector was transfered) */ + if(secPerformed != sectors_to_write) + { + (rc = ready(pdev, devNum, DOCH_STATUS_REG, (DOCH_READY | DOCH_DRQ | DOCH_BUSY | DOCH_ERROR), + DOCH_READY | DOCH_DRQ, DOCH_LONG_WAIT)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_output(): ATA not Ready (after data Xfer)\r\n"); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x , sector = %d \r\n"),rc,secPerformed)); + DISABLE_INTERRUPT(pdev); + return rc; + } + } + + offset += DOCH_SECTOR_SIZE; + } + } + else if (pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_MULT) + { + multCount = (FLByte)pdev->device[devNum].dwMulti_Current; + + for(secPerformed=0; secPerformed sectors_to_write) + multSecToWrite = (sectors_to_write - secPerformed); + else + multSecToWrite = multCount; + + /*Perform data xfer*/ + DOCHBLK_WRITE(pdev->bRegBase, (FLByte*)buf + offset,(multSecToWrite)); + + /* Check DRQ ready and not BSY before next data xfer */ + /* (don`t perform after LAST sector was transfered) */ + if((secPerformed + multSecToWrite) != sectors_to_write) + { + (rc = ready(pdev, devNum, DOCH_STATUS_REG, (DOCH_READY | DOCH_DRQ | DOCH_BUSY | DOCH_ERROR), + DOCH_READY | DOCH_DRQ, DOCH_LONG_WAIT)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_output(): ATA not Ready (after data Xfer)\r\n"); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x , sector = %d\r\n"),rc,secPerformed)); + DISABLE_INTERRUPT(pdev); + return rc; + } + } + + /*Advance number of written sectors and update pointer to buffer*/ + secPerformed += multSecToWrite; + offset += (multSecToWrite * DOCH_SECTOR_SIZE); + } + } + else + { + DBG_PRINT_ERR(FLZONE_ATA, "io_output(): Transfer Mode "); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("0x%x "), pdev->device[devNum].dataTransferMode)); + DBG_PRINT_ERR(FLZONE_ATA, "not supported\r\n"); + DISABLE_INTERRUPT(pdev); + return DOCH_FeatureNotSupported; + } /* End of if/else on pdev->device[devNum].dataTransferMode */ + + } /* End of else on if(pdev->bUseDMA) */ + /*******************end of different transfer modes ************************/ + + /*7. wait until device is ready */ + /*********************************/ + /* This might involve yielding the CPU and waiting for device interrupt, + * so we use DOCH_LONG_WAIT or DOCH_VERY_LONG_WAIT according to the operation + */ + rc = ready(pdev, devNum, DOCH_ALT_STATUS_REG, (DOCH_READY | DOCH_BUSY | DOCH_DRQ), + DOCH_READY, dwLongWait); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_output(): ATA not Ready (after all data completed)\r\n"); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x \r\n"),rc)); + } + + /*8. check operation's status */ + /******************************/ + /* this also clear IRQ */ + status = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_STATUS_REG); + if((status & (DOCH_BUSY | DOCH_READY | DOCH_ERROR)) != DOCH_READY) + { + DISABLE_INTERRUPT(pdev); + DBG_PRINT_ERR(FLZONE_ATA, "io_output(): after completion status register indicates a problem: "); + DBG_PRINT_ERR_PRM(FLZONE_ATA,(FLTXT("reported status 0x%x\r\n"),status)); + if((status & DOCH_ERROR) == DOCH_ERROR) + { + return DOCH_ATAErrorDetected; + } + return DOCH_ATANotReady; + } + DISABLE_INTERRUPT(pdev); + return rc; +} + +/****************************************************************************** + * * + * i o _ c t r l * + * * + * Pass command 'cmd' to DOCH device. * + * * + * Parameters : * + * pdev : device to act on * + * regs : DOCH_Registers * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ +DOCH_Error io_ctrl ( DOCH_Socket * pdev, + FLSNative devNum, + DOCH_Registers * regs) +{ + DOCH_Error rc; + FLSNative status; + FLDword dwLongWait= ((regs->bCommandStatus!= DOCH_VSCMD_PARTITION_MANAGEMENT)? DOCH_LONG_WAIT:\ + ((regs->bFeaturesError ==DOCH_DELETE_PARTITIONS)? DOCH_VERY_LONG_WAIT:DOCH_LONG_WAIT)); + + +#ifdef CX_ATA_SNIFFER + extern FILE * ataLogFile; + + ataCmdRec.bAtaCmdType = CX_ATATYPE_CTRL; + ataCmdRec.dwDevNum=devNum; + ataCmdRec.regs=*regs; + if (!fwrite(&ataCmdRec,sizeof(AtaCmdRec_S),1,ataLogFile)) + { + DBG_PRINT_ERR(FLZONE_ATA, "\r\nError:io_ctrl():Cannot write command rec to file \r\n"); + return DOCH_ATA_ERROR_ABORT; + } + fflush(ataLogFile); +#endif /*CX_ATA_SNIFFER*/ + + /* First we write the device head register to ensure we are communicating + with the right device...*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, (regs->bDriveHead|DOCH_LBA)); + DOCH_DELAY_AFTER_DEVICE_SWITCH(pdev,((regs->bDriveHead & DOCH_DEVICE) == DOCH_DEVICE)); + + /*Wait for DOCH BUSY flag to clear*/ + if ((rc = ready(pdev, devNum, DOCH_ALT_STATUS_REG, (DOCH_READY|DOCH_BUSY|DOCH_DRQ),DOCH_READY, DOCH_SHORT_WAIT)) != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_ctrl(): ATA not Ready (before command)\r\n"); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x \r\n"),rc)); + return rc; + } + + + /*Write ATA registers*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_FEATURES_REG, regs->bFeaturesError); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_CNT_REG, regs->bSectorCount); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_NO_REG, regs->bSectorNumber); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CYLINDER_LOW_REG, regs->bCylLow); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CYLINDER_HIGH_REG, regs->bCylHigh); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_COMMAND_REG, regs->bCommandStatus); + + /* wait until device is ready */ + rc = ready(pdev, devNum, DOCH_STATUS_REG, (DOCH_READY | DOCH_BUSY), + DOCH_READY, dwLongWait); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_ctrl(): ATA not Ready (after command)\r\n"); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x \r\n"),rc)); + return rc; + } + + /* check operation's status; this also clear IRQ */ + status = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_STATUS_REG); + if((status & (DOCH_BUSY | DOCH_READY | DOCH_ERROR)) != DOCH_READY) + { + DBG_PRINT_ERR(FLZONE_ATA, "io_ctrl(): after completion status register indicates a problem: "); + DBG_PRINT_ERR_PRM(FLZONE_ATA,(FLTXT("reported status 0x%x\r\n"),status)); + if((status & DOCH_ERROR) == DOCH_ERROR) + { + return DOCH_ATAErrorDetected; + } + return DOCH_ATANotReady; + } + + + return rc; +} + +DOCH_Error retrieveAndPrintAtaDebug(DOCH_Socket* pdev) +{ + DOCH_Error rc = DOCH_OK; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + /*FLWord numOfDataBytes;*/ + FLWord currentINTEnabled, currentDMAEnabled, currentBurstEnabled; + + tffsset(&in_regs, 0, sizeof(in_regs)); + in_regs.bFeaturesError = DOCH_RETRIEVE_DBG_MSG; + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + in_regs.bSectorCount = 1; + in_regs.bDriveHead = DOCH_SELECT_DEV(pdev->bAtaDevNum); + + /* Disable interrupts */ + /* Disable DMA/Burst */ + /* (retain original values)*/ + currentINTEnabled = pdev->bUseInterrupt; + currentDMAEnabled = pdev->bUseDMA; + currentBurstEnabled = pdev->bUseBurst; + pdev->bUseInterrupt = FALSE; + pdev->bUseDMA = FALSE; + pdev->bUseBurst = FALSE; + + + /*Perform debug ocommand*/ + rc = io_input(pdev, 0, &in_regs, ataDBG, 1); + + /*Revert interrupts/DMA/Burst to original state*/ + pdev->bUseInterrupt = currentINTEnabled; + pdev->bUseDMA = currentDMAEnabled; + pdev->bUseBurst = currentBurstEnabled; + + + /*Retrieve ATA out registers*/ + rc = get_out_registers(pdev, 0, &out_regs); + if(rc != DOCH_OK) + return rc; + + /*numOfDataBytes = (out_regs.bSectorNumber + (out_regs.bCylLow<<8));*/ + + if(ataDBG[0] != '\0') + { + DBG_PRINT_ERR(FLZONE_ATA, "\r\n~~~~~~~~~~~~~~~~~~~~~~~~~"); + DBG_PRINT_ERR(FLZONE_ATA, "\r\n*** ETFFS Debug string: "); + DBG_PRINT_ATA(FLZONE_ATA,(FLTXT_VAR(ataDBG))); + DBG_PRINT_ERR(FLZONE_ATA, " ***"); + DBG_PRINT_ERR(FLZONE_ATA, "\r\n~~~~~~~~~~~~~~~~~~~~~~~~~\r\n"); + } + + return rc; +} + +/****************************************************************************** + * * + * d o c h _ c o m m a n d * + * * + * Sends 'cmd' command to DOCH device. * + * * + * Parameters : * + * socketNo : Socket # (0...DOCH_MAX_SOCKETS-1) * + * in_regs : DOCH input registers values * + * out_regs : DOCH output registers values * + * buf : user buffer * + * secNum : # of sectors (for data transfer commands) * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ + +DOCH_Error doch_command ( FLSNative socketNo, + FLSNative devNum, + DOCH_Registers* in_regs, + DOCH_Registers* out_regs, + void * buf, + FLNative secNum) +{ + DOCH_Socket* pdev; + DOCH_Error rc; + DOCH_Error rc2; + +#ifdef CX_ATA_SNIFFER + ataCmdRec.socketNo=socketNo; +#endif /*CX_ATA_SNIFFER*/ + + /* Sanity Check*/ + /*=============*/ + if(socketNo > DOCH_MAX_SOCKETS - 1) + return DOCH_BadParameter; + + pdev = &sockets[socketNo]; + +#ifdef CHECK_POWER_ON_EVERY_COMMAND + /* Check if device was reset */ + rc = dochCheckPFSymptom(socketNo, pdev->bAtaDevNum, TRUE); + if(rc != DOCH_OK) + return rc; +#endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + +#ifdef DOCH_DMA_CONFIG + { + DMA_Params_S dmaParams; + + if(pdev->bUseDMA && (gDMAChannelOpen == 0)) + { + dmaParams.bOpType = DOCH_DMA_OPEN_CHANNEL; + DOCH_DMA_CONFIG(&dmaParams); + if(dmaParams.fDmaStatus != 0) + { + DBG_PRINT_ERR(FLZONE_API, "doch_command(): DOCH_DMA_OPEN_CHANNEL Failed\r\n"); + return DOCH_GeneralFailure; + } + + gDMAChannelOpen = DOCH_GLOBAL_BOOL_PATTERN; + + DBG_PRINT_FLOW(FLZONE_ATA, "\r\nDMA Channel opened\r\n"); + } + + } +#endif /*DOCH_DMA_CONFIG*/ + + /*Branch to proper IO routine according to ATA command*/ + switch ((DOCH_Command)(in_regs->bCommandStatus)) + { + /* Vendor-Specific ATA commands */ + + case DOCH_VSCMD_READ_PARTITION: + case DOCH_VSCMD_READ_CALCULATED_HASH: + case DOCH_VSCMD_READ_ORIGINAL_HASH: + rc = io_input (pdev, devNum, in_regs, buf, secNum); + break; + + case DOCH_VSCMD_WRITE_PARTITION: + case DOCH_VSCMD_WRITE_FLEXI: + case DOCH_VSCMD_WRITE_GIVEN_HASH: + rc = io_output (pdev, devNum, in_regs, buf, secNum); + break; + + case DOCH_VSCMD_OPTIMIZE_PARTITION_SECTORS: + case DOCH_VSCMD_ERASE_PARTITION_SECTORS: + case DOCH_VSCMD_WRITE_CALCULATED_HASH: + rc = io_ctrl (pdev, devNum, in_regs); + break; + + case DOCH_VSCMD_PARTITION_MANAGEMENT: + switch((DOCH_DeviceCtrlOp)(in_regs->bFeaturesError)) + { + + case DOCH_SET_DEFAULT_PARTITION: + case DOCH_DELETE_PARTITIONS: + rc = io_ctrl (pdev, devNum, in_regs); + break; + + case DOCH_GET_PARTITION_INFO: + case DOCH_GET_PARTITION_USER_ATTR: + rc = io_input (pdev, devNum, in_regs, buf, secNum); + break; + + case DOCH_SET_PARTITION_PROTECTION: + case DOCH_SET_PARTITION_USER_ATTR: + case DOCH_ADD_PARTITION: + case DOCH_SECURE_ERASE: + rc = io_output (pdev, devNum, in_regs, buf, secNum); + break; + + default: + return DOCH_UnknownCmd; + } + break; + + case DOCH_VSCMD_ACCESS_CONTROL: + switch((DOCH_SecurityCtrlOp)(in_regs->bFeaturesError)) + { + case DOCH_DISABLE_ACCESS: + rc = io_ctrl (pdev, devNum, in_regs); + break; + + case DOCH_RX_DOCH_PUBLICKEY: + case DOCH_VERIFY_HOST_KEY: +#ifdef FL_SLPP + case DOCH_SLPP_REPORT_LOCKED_RANGES: +#endif /*FL_SLPP*/ + rc = io_input (pdev, devNum, in_regs, buf, secNum); + break; + + case DOCH_EN_ACCESS_WPWD: + case DOCH_TX_HOST_PUBLICKEY: +#ifdef FL_SLPP + case DOCH_SLPP_UNLOCK_RANGE: + case DOCH_SLPP_UNLOCK_ENTIRE_PARTITION: + case DOCH_SLPP_LOCK_RANGE: + case DOCH_SLPP_STICKY_LOCK_RANGE: +#endif /*FL_SLPP*/ + rc = io_output (pdev, devNum, in_regs, buf, secNum); + break; + + default: + return DOCH_UnknownCmd; + } + break; + + case DOCH_VSCMD_EXT_DEVICE_CTRL: + switch((DOCH_DeviceCtrlOp)(in_regs->bFeaturesError)) + { + + case DOCH_SET_DATA_XFER_MODE: + case DOCH_ATOMIC_WRITE_SEQUENCE: + case DOCH_OPTIMIZE_MEDIA: + case DOCH_GET_RESET_STATUS: + case DOCH_NOTIFY_RESET: + case DOCH_NOTIFY_PLATFORM_RESUMED: + case DOCH_GET_CUSTOM_PARAM: + case DOCH_SET_CUSTOM_PARAM: + case DOCH_SET_POWER_MODE: + case DOCH_GET_POWER_MODE: + case DOCH_ACTIVATE_DEBUG_MODE: + case DOCH_SET_ALERT_LEVEL: + rc = io_ctrl (pdev, devNum, in_regs); + break; + + case DOCH_IDENTIFY_DISKONCHIP_DEVICE: + case DOCH_GET_EXTENDED_DEVICE_INFO: + case DOCH_GET_DISK_USER_ATTR: + case DOCH_GET_CONFIGURATION_DATA: + rc = io_input (pdev, devNum, in_regs, buf, secNum); + break; + + case DOCH_SET_DISK_USER_ATTR: + case DOCH_SET_CONFIGURATION_DATA: + rc = io_output (pdev, devNum, in_regs, buf, secNum); + break; + + default: + return DOCH_UnknownCmd; + } + break; + + case DOCH_VSCMD_EXT_SECURITY_CTRL: + switch((DOCH_SecurityCtrlOp)(in_regs->bFeaturesError)) + { + + case DOCH_SET_ALGORITHM_MODE: + case DOCH_AUTO_HASH_CONTROL: + case DOCH_SET_KEYS: + case DOCH_START_HASH_STREAM_CALC: + case DOCH_READ_STOP_HASH_STREAM_CALC: + rc = io_ctrl (pdev, devNum, in_regs); + break; + + case DOCH_REPORT_SUPPORTED_ALGORITHMS: + case DOCH_GET_ALGORITHM_CAPABILITIES: + case DOCH_RETURN_RANDOM_NUMBERS: + rc = io_input (pdev, devNum, in_regs, buf, secNum); + break; + + default: + return DOCH_UnknownCmd; + } + break; + + default: + return DOCH_UnknownCmd; + } + + /*If IO operation succeeded, retrieve device response from ATA registers + (calling routine might need some data back from the device) + Common IO Read/Write routines are excluded */ + switch( rc ) + { + case DOCH_OK: + if((in_regs->bCommandStatus != DOCH_VSCMD_READ_PARTITION) && + (in_regs->bCommandStatus != DOCH_VSCMD_WRITE_PARTITION) && + (in_regs->bCommandStatus != DOCH_VSCMD_WRITE_FLEXI)) + rc = get_out_registers(pdev, devNum, out_regs); + break; + + case DOCH_ATAErrorDetected: + rc = get_out_registers(pdev, devNum, out_regs); + break; + default: + break; + } + +#ifdef CHECK_POWER_ON_EVERY_COMMAND + /* Check if device was reset */ + rc2 = dochCheckPFSymptom(socketNo, pdev->bAtaDevNum, FALSE); + if(rc2 != DOCH_OK) + return rc2; +#endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + + /* If ATA debug was requested - retrieve and print buffer from Device */ + if(gDochAtaDebug == DOCH_GLOBAL_BOOL_PATTERN) + { + rc2 = retrieveAndPrintAtaDebug(pdev); + if(rc2 != DOCH_OK) + return rc2; + } + + return rc; +} + +/****************************************************************************** + * * + * d o c h _ a t a _ p a s s t h r u * + * * + * Pass-thru routine for ATA commands * + * * + * Parameters : * + * socketNo : Socket # (0...DOCH_MAX_SOCKETS-1) * + * ptOP : Data transfer type (In/Out/No) * + * in_regs : DOCH input registers values * + * out_regs : DOCH output registers values * + * buf : user buffer * + * secNum : Number of sectors (in case of data transfer) * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ + +DOCH_Error doch_ata_passthru ( FLSNative socketNo, + FLSNative devNum, + DOCH_PassThru_Op ptOP, + DOCH_Registers * in_regs, + DOCH_Registers * out_regs, + void * buf, + FLNative secNum) +{ + DOCH_Socket* pdev; + DOCH_Error rc = DOCH_OK; + DOCH_Error rc2; + + /* Sanity Check*/ + /*=============*/ + if(socketNo > DOCH_MAX_SOCKETS - 1) + return DOCH_BadParameter; + + pdev = &sockets[socketNo]; + + switch(ptOP) + { + case DOCH_PASSTHRU_NO_DATA: + rc = io_ctrl (pdev, devNum, in_regs); + break; + + case DOCH_PASSTHRU_DATA_IN: + rc = io_input (pdev, devNum, in_regs, buf, secNum); + break; + + case DOCH_PASSTHRU_DATA_OUT: + rc = io_output (pdev, devNum, in_regs, buf, secNum); + break; + + default: + return DOCH_UnknownCmd; + } + + /*If IO operation succeeded, retrieve device response from ATA registers + (calling routine might need some data back from the device)*/ + if(rc == DOCH_OK) + rc = get_out_registers(pdev, devNum, out_regs); + else + return rc; + + /* If ATA debug was requested - retrieve and print buffer from Device */ + if(gDochAtaDebug == DOCH_GLOBAL_BOOL_PATTERN) + { + rc2 = retrieveAndPrintAtaDebug(pdev); + if(rc2 != DOCH_OK) + return rc2; + } + + return rc; + +} + +/****************************************************************************** + * * + * c l e a r A T A I n t e r r u p t * + * * + * Clear ATA interrupt by simply reading the ATA status register * + * * + * Parameters : * + * pdev : device to perform operation on * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ +DOCH_Error clearATAInterrupt(FLSNative socketNo) +{ +#ifdef DOCH_USE_FUNC + DOCH_Socket* pdev; + + if(socketNo > DOCH_MAX_SOCKETS - 1) + return DOCH_BadParameter; + + pdev = &sockets[socketNo]; + + DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_STATUS_REG); + +#else /*DOCH_USE_FUNC*/ + + DOCHREAD_ATA_REG((&sockets[socketNo])->bRegBase, DOCH_STATUS_REG); + +#endif /*DOCH_USE_FUNC*/ + + return DOCH_OK; +} + + +/****************************************************************************** + * * + * g e t _ o u t _ r e g i s t e r s * + * * + * Retrieve ATA output registers values * + * * + * Parameters : * + * pdev : device to perform operation on * + * out_regs : DOCH output registers values * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ +DOCH_Error get_out_registers(DOCH_Socket* pdev, FLSNative devNum, DOCH_Registers* out_regs) +{ + DOCH_Error error = DOCH_OK; + + out_regs->bFeaturesError = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_ERROR_REG); + out_regs->bSectorCount = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_SECTOR_CNT_REG); + out_regs->bSectorNumber = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_SECTOR_NO_REG); + out_regs->bCylLow = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_CYLINDER_LOW_REG); + out_regs->bCylHigh = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_CYLINDER_HIGH_REG); + out_regs->bDriveHead = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_DRIVE_HEAD_REG); + out_regs->bCommandStatus = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_STATUS_REG); + out_regs->bContorlAltStatus = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_ALT_STATUS_REG); + + /*If an error was detected - return the error code*/ + if((out_regs->bCommandStatus & DOCH_ERROR) == DOCH_ERROR) + { + error = (DOCH_Error)out_regs->bFeaturesError; + + DBG_PRINT_ERR(FLZONE_ATA, "\r\nget_out_registers(): ATA Error\r\n"); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("error = 0x%x \r\n"),error)); + } + + return (error); +} + +/****************************************************************************** + * * + * d o c h _ g e t _ f l a g s * + * * + * Returns all device's flags (DOCH_USE_XXX) . * + * * + * Parameters : * + * socketNo : Socket # (0...DOCH_MAX_SOCKETS-1) * + * flags : device's flags will be stored there * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ + +DOCH_Error doch_get_flags (FLSNative socketNo, FLSNative devNum, FLDword * flags) +{ + /* Sanity check */ + if ((socketNo < 0) || (socketNo >= DOCH_MAX_SOCKETS) || (flags == NULL)) + return DOCH_BadParameter; + + *flags = sockets[socketNo].device[devNum].flags; + + return DOCH_OK; +} + + +/****************************************************************************** + * * + * d o c h _ s e t _ f l a g s * + * * + * Add various DOCH_USE_... flags to existing device's flags. * + * * + * Parameters : * + * socketNo : Socket # (0...DOCH_MAX_SOCKETS-1) * + * flags : collection of DOCH_USE_... flags to add * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ + +DOCH_Error doch_set_flags (FLSNative socketNo, FLSNative devNum, FLDword flags) +{ + /* args sanity check */ + if ((socketNo < 0) || (socketNo >= DOCH_MAX_SOCKETS)) + return DOCH_BadParameter; + + sockets[socketNo].device[devNum].flags = flags; + + return DOCH_OK; +} + + + +/****************************************************************************** + * * + * d o c h _ r e s e t * + * * + * Reset ATA Protocol . * + * * + * Parameters : * + * socketNo : Socket # (0...DOCH_MAX_SOCKETS-1) * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ + +DOCH_Error doch_reset (DOCH_Socket* pdev) +{ +#ifndef DOCH_DISABLE_RESET + FLDword tries; + FLDword i = 0; + FLByte status; + + DBG_PRINT_FLOW(FLZONE_ATA, "doch_reset() - enter\r\n"); + /*Protect against access time set to 0*/ + if(gDochAccessNanosec == 0) + { + DBG_PRINT_ERR(FLZONE_ATA,"doch_reset(): Failed with bad parameter access time set to 0 \r\n"); + return DOCH_BadParameter; + } + + /* reset DOCH */ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CONTROL_REG, DOCH_ATA_SRST); + + /* need to add delay before writing twice in short time to the control register*/ + DOCH_DELAY_BEFORE_ACCESSING_SAME_REGISTER; + + /* cancel DOCH reset */ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CONTROL_REG, 0); + + + /*Master is selected*/ + /* Wait for: + READY bit asserted + BUSY bit de-asserted + DRQ bit de-asserted + */ + tries = (DOCH_SHORT_WAIT* (1000000UL / gDochAccessNanosec)); + for(i=0; ibRegBase, DOCH_STATUS_REG); + if( (status & (DOCH_READY | DOCH_BUSY | DOCH_DRQ)) == DOCH_READY) + break; + } + if (!tries) + { + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("\r\ndoch_reset(): Device#0 not ready (after reset): #0x%x \r\n"), status)); + return DOCH_TimedOut; + } + +#if (ATA_MAX_NUM_OF_DEVICES==2) + /*select slave and make sure slave is ready*/ + if (pdev->wNumOfDevices >1) + { + DOCH_Error rc; +#ifdef DOCH_NO_SUPPORT_PARALLEL_SDK_INSTANCES + pdev->bLastDevNum=0;/*Master was the last one that was selected*/ +#endif /*DOCH_NO_SUPPORT_PARALLEL_SDK_INSTANCES*/ + /* 3 accesses in each iteration */ + tries = (DOCH_SHORT_WAIT* (1000000UL / (gDochAccessNanosec*3))); + while (tries) + { + /*Set active ATA device*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, DOCH_SELECT_DEV1); + DOCH_DELAY_AFTER_DEVICE_SWITCH(pdev,1); + + /* Before trying to identify Dev1, check its CHIP_ID*/ + rc = doch_check_chipID(pdev->wSocketNo); /*caller responsibility to set device head register*/ + status = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_STATUS_REG); + if (rc == DOCH_OK) + { /*found chip ID - check readiness*/ + if((status & (DOCH_READY | DOCH_BUSY)) == DOCH_READY) + { + DBG_PRINT_FLOW_PRM(FLZONE_ATA, (FLTXT("Socket #%d dev1"), pdev->wSocketNo)); + DBG_PRINT_FLOW(FLZONE_ATA, " - Found ChipID !\r\n"); + break; + } + } + DOCH_DELAY_BEFORE_ACCESSING_SAME_REGISTER; + tries--; + } + + if (!tries) + { + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("\r\ndoch_reset(): Device#1 not ready (after reset): #0x%x \r\n"), status)); + return DOCH_TimedOut; + } + DOCH_DELAY_BEFORE_ACCESSING_SAME_REGISTER; + /*Set original ATA device*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, DOCH_SELECT_DEV(pdev->bAtaDevNum)); + DOCH_DELAY_AFTER_DEVICE_SWITCH(pdev,pdev->bAtaDevNum); + DOCH_DELAY_BEFORE_ACCESSING_SAME_REGISTER; + } +#endif /*(ATA_MAX_NUM_OF_DEVICES==2)*/ + DBG_PRINT_FLOW(FLZONE_ATA, "doch_reset() - exit (OK) \r\n"); +#endif /*DOCH_DISABLE_RESET*/ + return DOCH_OK; +} + +/****************************************************************************** + * * + * u p d a t e _ d e v i c e _ i n f o * + * * + * Update device structure based on diskOnChip device info structure * + * * + * Parameters : * + * pdev : DOCH_Socket * + * diskOnChipDeviceInfo : DOCH_DeviceInfo * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ +DOCH_Error update_device_info(DOCH_Socket* pdev, + DOCH_DeviceInfo* diskOnChipDeviceInfo, + FLSNative devNum) +{ + IOreq ioreq; + + /*TBD - BYTE???*/ + FLByte drqSize ; + + if((pdev == NULL) || (diskOnChipDeviceInfo == NULL)) + return DOCH_BadParameter; + drqSize = 1<<((FLByte)((diskOnChipDeviceInfo->dwCommandFlagsOrStatuses & DOCH_DCFSB_CURRENT_MULTI_SECTOR) >> DOCH_DCFSO_CURRENT_MULTI_SECTOR)); + + /*Update device structure*/ + /*=======================*/ + pdev->device[devNum].wNumOfPartitions = diskOnChipDeviceInfo->wTotalNumOfPartitions; + + pdev->device[devNum].dataTransferMode = + (DOCH_TransferMode)((diskOnChipDeviceInfo->dwCommandFlagsOrStatuses & DOCH_DCFSB_CURRENT_XFER_MODE) >> DOCH_DCFSO_CURRENT_XFER_MODE); + + /*Set XFER mode*/ + /*-------------*/ + doch_setTransferMode(pdev->wSocketNo, devNum, pdev->device[devNum].dataTransferMode, drqSize); + + if(pdev->wNumOfDevices == 0) + { + /*Retrieve device user attributes*/ + tffsset(&ioreq, 0, sizeof(ioreq)); + DOCH_SET_SOCKET_TO_IOREQ_HANDLE(&ioreq, pdev->wSocketNo); + ioreq.irData = &devUserAttr; + DOCHGetDiskUserAttributes(&ioreq); + + /*Extract span information from device attributes*/ + tffscpy(&pdev->sSpanData, &devUserAttr.sdkAttributes.sSpanInfo, sizeof(pdev->sSpanData)); + } + + return DOCH_OK; +} + +/*----------------------------------------------------------------------*/ +/* d o c h S e t M u t e x */ +/* */ +/* Notifies the start and end of a file-system operation. */ +/* */ +/* Parameters: */ +/* socketNum : Socket number */ +/* state : DOCH_ON (1) = operation entry */ +/* DOCH_OFF(0) = operation exit */ +/* partition : Partition number of the drive */ +/* */ +/*----------------------------------------------------------------------*/ +DOCH_Error dochSetMutex(FLByte socketNum, FLBoolean state, FLByte partition) +{ + DOCH_Socket* pdev; + + if(socketNum > DOCH_MAX_SOCKETS - 1) + return DOCH_BadParameter; + + pdev = &sockets[socketNum]; + + if (state == DOCH_ON) /* Set busy to ON */ + { + if (!flTakeMutex(&pdev->mutex)) + { + DBG_PRINT_ERR(FLZONE_ATA, "\r\ndochSetMutex Failed to set mutex\r\n"); + return DOCH_DriveNotAvailable; + } + } + else /* Set busy to OFF */ + { + flFreeMutex(&pdev->mutex); + } + + return DOCH_OK; +} + +/****************************************************************************** + * * + * d o c h _ f i n d _ b a s e _ a d d r e s s * + * * + * Calculate base address, try getting CHIP_ID from the device * + * * + * Parameters : * + * socketNo : Socket # (0...DOCH_MAX_SOCKETS-1) * + * dwAddress : Device address * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ +static +DOCH_Error doch_find_base_address(FLSNative socketNo, + FLDword dwAddress) +{ + void* win; + + /*Retreive socket pointer from devices array*/ + DOCH_Socket* pdev; + + if(socketNo > DOCH_MAX_SOCKETS - 1) + return DOCH_BadParameter; + + pdev = &sockets[socketNo]; + + /* Save the physical address */ + pdev->dwPhysicalAddress = dwAddress; + + /* Get pointer to base of DOCH register set */ + win = (void*)(dwAddress); + + pdev->bRegBase = (volatile FLByte FAR0*)physicalToPointer((FLDword)win,DOCH_MEM_WIN_SIZE,0); + + return DOCH_OK; +} + +/****************************************************************************** + * * + * d o c h _ f i n d _ b a s e _ a d d r e s s * + * * + * Calculate base address, try getting CHIP_ID from the device * + * caller responsibility to set device head register * + * * + * Parameters : * + * socketNo : Socket # (0...DOCH_MAX_SOCKETS-1) * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ +static +DOCH_Error doch_check_chipID(FLSNative socketNo) +{ + FLWord chipID1 = 0; + FLWord chipID2 = 0; + + /*Retrieve socket pointer from devices array*/ + DOCH_Socket* pdev; + + if(socketNo > DOCH_MAX_SOCKETS - 1) + return DOCH_BadParameter; + + pdev = &sockets[socketNo]; + +/* no need to set device head register here- caller responsibility*/ + + /*Check ChipID*/ + /*============*/ + /*Read Chip ID #1*/ + chipID1 = doch_getConfigReg16(pdev, HIB_CHIPID1_REG); + /*Read Chip ID #2*/ + chipID2 = doch_getConfigReg16(pdev, HIB_CHIPID2_REG); + + + /*Check that Chip IDs match*/ + if((chipID1 + chipID2) == 0xFFFF) + { + if((chipID1 != DOCH_CHIP_ID_H3) && (chipID1 != DOCH_CHIP_ID_H4) && (chipID1 != DOCH_CHIP_ID_H5)) + { + DBG_PRINT_FLOW_PRM(FLZONE_ATA, (FLTXT("\r\nUnknown ChipID: #%d \r\n"), chipID1)); + } + else + { + /* + DBG_PRINT_FLOW_PRM(FLZONE_ATA, (FLTXT("\r\nSocket #%d - ChipID OK"), socketNo)); + DBG_PRINT_FLOW(FLZONE_ATA, "\r\nDevice Found: "); + if(chipID1 == DOCH_CHIP_ID_H3) + DBG_PRINT_FLOW(FLZONE_ATA, "H3"); + if(chipID1 == DOCH_CHIP_ID_H4) + DBG_PRINT_FLOW(FLZONE_ATA, "H4"); + if(chipID1 == DOCH_CHIP_ID_H5) + DBG_PRINT_FLOW(FLZONE_ATA, "H5"); + */ + return DOCH_OK; + } + } + else + { + DBG_PRINT_FLOW_PRM(FLZONE_ATA, (FLTXT("\r\nSocket #%d - ChipID Not Found -"), socketNo)); + DBG_PRINT_FLOW_PRM(FLZONE_ATA, (FLTXT(" ChipID#1 0x%x , ChipID#2 0x%x\r\n"), chipID1, chipID2 )); + } + + return DOCH_AdapterNotFound; +} + +DOCH_Error setConfigHWItem(DOCH_HwConfigType configHWItem) +{ + DOCH_Error rc; + IOreq ioreq; + + tffsset(&ioreq, 0, sizeof(ioreq)); + + ioreq.irFlags = configHWItem; + ioreq.irLength = gConfigHWDefaults[configHWItem]; + rc = DOCHConfigHW(&ioreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_ATA, "\r\nsetConfigHWItem(): Failed setting config Item "); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("#%d "),configHWItem)); + DBG_PRINT_ERR(FLZONE_ATA, "\r\nwith status: "); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("0x%x \r\n"),rc)); + + return rc; + } + + return DOCH_OK; +} +/****************************************************************************** + * * + * d o c h _ c o n f i g C o m m o n * + * * + * initializes config registers common to both floors * + * * + * Parameters : * + * pdev : device descriptor * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ +DOCH_Error doch_configCommon(DOCH_Socket* pdev) +{ + + /*Dummy write to exit virtual mode*/ + /*(Don't worry about the value it is later updated by calling setConfigHWItem(DOCH_IPL_CTRL))*/ + DOCHWRITE_CTRL_REG (pdev->bRegBase, HIB_CHIPID2_REG, 0); + + /*The following registers effect both floors - no need to select each floor*/ + if (gSdkInitDone != DOCH_GLOBAL_BOOL_PATTERN) + { /*initialize - set defaults*/ + /*Set Endian Control Register */ + doch_setConfigReg16 (pdev,HIB_ENDIAN_CTRL_REG,gConfigHWDefaults[DOCH_ENDIAN_CTRL]); + + /*Set Power down register */ + doch_setConfigReg16 (pdev,HIB_POWER_DOWN_REG,gConfigHWDefaults[DOCH_POWER_DOWN]); + + /*Set S/W Lock Control register + (This will perform SW lock as needed) */ + doch_setConfigReg16 (pdev,HIB_SW_LOCK_REG,gConfigHWDefaults[DOCH_SLOCK]); + + /*Set Operation Mode Register */ + doch_setConfigReg16 (pdev,HIB_OPERATION_MODE_REG,gConfigHWDefaults[DOCH_OPERATION_MODE_CTRL]); + }else + { /*recover last values*/ + if(configRegValueSet.wEndianCtrlSet) + { + doch_setConfigReg16 (pdev,HIB_ENDIAN_CTRL_REG,configRegValue.wEndianCtrl); + } + if(configRegValueSet.wPowerDownSet) + { + doch_setConfigReg16 (pdev,HIB_POWER_DOWN_REG,configRegValue.wPowerDown); + } + if (configRegValueSet.wSWLockSet) + { + doch_setConfigReg16 (pdev,HIB_SW_LOCK_REG,configRegValue.wSWLock); + } + if (configRegValueSet.wOperationModeSet) + { + doch_setConfigReg16 (pdev,HIB_OPERATION_MODE_REG,configRegValue.wOperationMode); + } + } + + +#ifdef DOCH_NO_SUPPORT_PARALLEL_SDK_INSTANCES + /* clear lastDevNum before initializing floors*/ + pdev->bLastDevNum = 0xFF; +#endif /*DOCH_NO_SUPPORT_PARALLEL_SDK_INSTANCES*/ + + + return DOCH_OK; + +} +/****************************************************************************** + * * + * d o c h _ c o n f i g F l o o r * + * * + * initializes config registers of specific floor * + * NOTE: caller responsibility to select floor * + * * + * Parameters : * + * pdev : device descriptor * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ +DOCH_Error doch_configFloor(DOCH_Socket* pdev) +{ + /*The following registers should be set only after device was successfully selected*/ + + if (gSdkInitDone!= DOCH_GLOBAL_BOOL_PATTERN) + { /*initialize - set defaults*/ + /*Set IPL control register */ + doch_setConfigReg16 (pdev,HIB_IPL_CONTROL_REG,gConfigHWDefaults[DOCH_IPL_CTRL]); + + /*Set DMA Control register */ + doch_setConfigReg16 (pdev,HIB_DMA_CTRL_REG,gConfigHWDefaults[DOCH_DMA_CTRL]); + + /*Set DMA Negation register */ + doch_setConfigReg16 (pdev,HIB_DMA_NEGATION_REG,gConfigHWDefaults[DOCH_DMA_NEGATION_CTRL]); + + }else + { /*recover last values*/ + if(configRegValueSet.wIPLCtrlSet) + { + doch_setConfigReg16(pdev, HIB_IPL_CONTROL_REG, configRegValue.wIPLCtrl); + } + + if(configRegValueSet.wDMACtrlSet) + { + doch_setConfigReg16(pdev, HIB_DMA_CTRL_REG, configRegValue.wDMACtrl); + } + + if(configRegValueSet.wEndianNegationSet) + { + doch_setConfigReg16(pdev, HIB_DMA_NEGATION_REG, configRegValue.wEndianNegation); + } + } + + return DOCH_OK; + +} + +/****************************************************************************** + * * + * d o c h _ c o n f i g A n d I D * + * * + * Try finding a DOCH device on the requested address * + * initializes config registers that are common to both floors * + * reads chipID of floor 0 * + * initializes config registers of floor 0 * + * * + * Parameters : * + * socketNo : Socket # (0...DOCH_MAX_SOCKETS-1) * + * DOCH_InitSocket : runtime socket init data * + * pDev : device to act on * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ +static DOCH_Error doch_configAndID(DOCH_Socket* pdev, FLSNative socketNo, DOCH_InitSocket initSocket) +{ + DOCH_Error rc; + + /*Try finding a DOCH device on the requested address*/ + /*==================================================*/ + gSdkDOCAddressObtained = 0; + + rc = doch_find_base_address(socketNo, initSocket.nDeviceAddress); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_ATA, "Socket "); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("#%d "), socketNo)); + DBG_PRINT_ERR(FLZONE_ATA, "NOT found !\r\n"); + + return rc; + } + + /* Global indication that the DOC address was obtained */ + gSdkDOCAddressObtained = DOCH_GLOBAL_BOOL_PATTERN; + + /*Set PCI/PortaDoc window offset register*/ + /*=======================================*/ + if(gAccessLayerType == DOCH_AL_NOR) + { + if(gMemWindowType == MEM_WIN_8KB) + { + + if (!DOCH_SET_WINDOW_OFFSET(TRUE, pdev->bRegBase)) + { + return DOCH_GeneralFailure; + } + + } + else + { + if (!DOCH_SET_WINDOW_OFFSET(FALSE, pdev->bRegBase)) + { + return DOCH_GeneralFailure; + } + } + } + + /* Set HW Config Items */ + /*=====================*/ + /*The following registers effect both floors - no need to select each floor*/ + doch_configCommon(pdev); + + /*Set device to master before checking CHIP ID*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, DOCH_SELECT_DEV0); + DOCH_DELAY_AFTER_DEVICE_SWITCH(pdev,0); + + /*initialize config registers of floor 0*/ + doch_configFloor(pdev); + + + /*Check ChipID*/ + /*============*/ + rc = doch_check_chipID(socketNo);/*caller responsibility to set device head register*/ + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_ATA, "Socket "); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("#%d device#0"), socketNo)); + DBG_PRINT_ERR(FLZONE_ATA, " - ChipID FAILED !\r\n"); + + return rc; + } + + return DOCH_OK; + +} + +static DOCH_Error doch_init_8kb(DOCH_Socket* pdev, FLSNative socketNo, DOCH_InitSocket initSocket) +{ + DOCH_Error rc; + + /*Set mem window type and size*/ + gMemWindowType = MEM_WIN_8KB; + gDochMemWinSize = DOCH_MEM_WIN_SIZE_8KB; + + /*Set addresses*/ + gHibContRegAreaAddress = HIB_CORE_ADDRESS_8KB+DOCH_CONT_REG_AREA_8KB_OFFSET; + gHibDataPortAreaAddress = HIB_CORE_ADDRESS_8KB+DOCH_DATA_PORT_AREA_8KB_OFFSET; + gHibConfigRegAreaAddress = HIB_CORE_ADDRESS_8KB+DOCH_CONFIG_REG_AREA_8KB_OFFSET; + + DBG_PRINT_FLOW(FLZONE_ATA, "Try 8KB window...\r\n"); + + /*Config HW and check ChipID*/ + rc = doch_configAndID(pdev, socketNo, initSocket); + + if(rc == DOCH_OK) + DBG_PRINT_FLOW(FLZONE_ATA, "Memory window is 8KB\r\n"); + + return rc; +} + +static DOCH_Error doch_init_128kb(DOCH_Socket* pdev, FLSNative socketNo, DOCH_InitSocket initSocket) +{ + DOCH_Error rc; + + /*Set mem window type*/ + gMemWindowType = MEM_WIN_128KB; + gDochMemWinSize = DOCH_MEM_WIN_SIZE_128KB; + + /*Set addresses*/ + gHibContRegAreaAddress = HIB_CORE_ADDRESS_128KB+DOCH_CONT_REG_AREA_128KB_OFFSET; + gHibDataPortAreaAddress = HIB_CORE_ADDRESS_128KB+DOCH_DATA_PORT_AREA_128KB_OFFSET; + gHibConfigRegAreaAddress = HIB_CORE_ADDRESS_128KB+DOCH_CONFIG_REG_AREA_128KB_OFFSET; + + DBG_PRINT_FLOW(FLZONE_ATA, "Try 128KB window...\r\n"); + + /*Config HW and check ChipID*/ + rc = doch_configAndID(pdev, socketNo, initSocket); + + if(rc == DOCH_OK) + DBG_PRINT_FLOW(FLZONE_ATA, "Memory window is 128KB\r\n"); + + return rc; +} + +/****************************************************************************** + * * + * d o c h _ A T A s t d _ I D E N T I F Y _ D E V I C E * + * * + * Identify Device by using ATA standard IDENTIFY DEVICE command. * + * * + * Parameters : * + * socketNo : Socket # (0...DOCH_MAX_SOCKETS-1) * + * DOCH_InitSocket : runtime socket init data * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ +static DOCH_Error doch_ATAstd_IDENTIFY_DEVICE(FLSNative socketNo, FLSNative devNum) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + + tffsset(&in_regs, 0, sizeof(in_regs)); + in_regs.bDriveHead = DOCH_SELECT_DEV(devNum); + in_regs.bCommandStatus = DOCH_CMD_IDENTIFY_DEV; + + gIgnoreErrorBit = 1; + + rc = doch_ata_passthru ( socketNo, + devNum, + DOCH_PASSTHRU_DATA_IN, + &in_regs, + &out_regs, + &sockets[socketNo].device[devNum].driveParameters, + 1); + + gIgnoreErrorBit = 0; + + if(rc != DOCH_OK) + return DOCH_DiskNotFound; + + return DOCH_OK; +} + +/****************************************************************************** + * * + * d o c h _ i n i t _ w i n d o w * + * * + * Initialize DOCH socket (only first floor is initialized) * + * * + * Parameters : * + * socketNo : Socket # (0...DOCH_MAX_SOCKETS-1) * + * DOCH_InitSocket : runtime socket init data * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ +DOCH_Error doch_init_window (FLSNative socketNo, DOCH_InitSocket initSocket) +{ + DOCH_Error rc; + DOCH_Socket* pdev; + FLByte j; + + /* Args sanity check */ + if ((socketNo < 0) || (socketNo >= DOCH_MAX_SOCKETS)) + return DOCH_BadParameter; + + /*Retrieve socket pointer from devices array*/ + pdev = &sockets[socketNo]; + + for(j=0; j < 2 ; j++) + { + /*Try identifying device on both 8KB and 128KB memory windows*/ + /*===========================================================*/ + + #ifdef DOCH_ASSUME_128KB_WINDOW + /*If 128KB window is assumed, skip checking 8KB window*/ + j = 1; + #endif /*DOCH_ASSUME_128KB_WINDOW*/ + + #ifdef DOCH_ASSUME_8KB_WINDOW + /*If 8KB window is assumed, do not continue checking 128KB window*/ + if(j == 1) + return DOCH_AdapterNotFound; + #endif /*DOCH_ASSUME_8KB_WINDOW*/ + + if(j==0) /*Try 8KB window*/ + { + rc = doch_init_8kb(pdev, socketNo, initSocket); + if(rc == DOCH_OK) + return DOCH_OK; + } + else /*Try 128KB window*/ + { + rc = doch_init_128kb(pdev, socketNo, initSocket); + if(rc != DOCH_OK) + return rc; + } + + } + + return DOCH_OK; +} + +/****************************************************************************** + * * + * d o c h _ i n i t _ f l o o r s * + * * + * initialization sequence for each floor (MASTER \SLAVE) * + * makes sure floor is ready * + * in case of ATA_MAX_NUM_OF_DEVICES == 2 both floors should be initialized * + * * + * Parameters : * + * pdev : device to act on * + * bFloor : 0-MASTER , 1-SLAVE * + * bConfFloor : TRUE - config floor * + * FALSE - do not config floor * + * (Master might be already set during window search) * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ +DOCH_Error doch_init_floors (DOCH_Socket* pdev,FLByte bConfFloor,FLByte * bFloorsNum) +{ + DOCH_Error rc =DOCH_OK; + FLDword dwTimes=0,i; + FLWord status; + + (*bFloorsNum) =0; + /* MASTER*/ + if (bConfFloor) + { + /* when function call is not from init sequence- */ + /* device head was not set yet and floor was not configured*/ + /*Set active ATA device*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, DOCH_SELECT_DEV0); + DOCH_DELAY_AFTER_DEVICE_SWITCH(pdev,0); + doch_configFloor(pdev); + } + /* during init - no need to rewrite device head register */ + /* it was set inside doch_init_xxkb */ + /* chip ID for device#0 was already checked */ + + /*Disable interrupts (will be enabled later per API decision)*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CONTROL_REG, DOCH_ATA_NIEN); + + dwTimes = (DOCH_MOUNT_WAIT* (1000000UL / gDochAccessNanosec)); + for(i=0; ibRegBase, DOCH_STATUS_REG); + if((status & (DOCH_READY | DOCH_BUSY)) == DOCH_READY) + break; + } + + if (i==dwTimes) + { + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("\r\nDoch_init_floors(): Device#0 not ready - status: 0x%x \r\n"),status)); + rc = DOCH_DiskNotFound; + } + else + { + (*bFloorsNum)++; + } + +#if (ATA_MAX_NUM_OF_DEVICES==2) + +#ifdef FL_UTILS_QUICK_INIT +if (gDochQuickInit != DOCH_GLOBAL_BOOL_PATTERN) +{ +#endif /*FL_UTILS_QUICK_INIT*/ + + if (rc==DOCH_OK) + { /* SLAVE*/ + FLSNative socketNo = pdev->wSocketNo; + dwTimes *= gDochAccessNanosec / 1000000UL; + rc = DOCH_GeneralFailure; + /* SLAVE device cannot be selected until it becomes ready*/ + /* no way for checking slave readiness without selecting it first...*/ + /* Therefore make several trials to select it and read it's chip ID */ + do { + /*Set active ATA device*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, DOCH_SELECT_DEV1); + DOCH_DELAY_AFTER_DEVICE_SWITCH(pdev,1); + + /* Before trying to identify Dev1, check its CHIP_ID*/ + rc = doch_check_chipID(socketNo); /*caller responsibility to set device head register*/ + + if (rc != DOCH_OK) + { + DOCH_DELAY_BETWEEN_CHIP_ID_TRIALS_FOR_SLAVE; + }else + { + /*found chip ID - check readiness*/ + status = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_STATUS_REG); + if((status & (DOCH_READY | DOCH_BUSY)) == DOCH_READY) + { + /*dwTimes could be bigger than max trials already on first iteration (unlikely, yet can happen), + but slave is ready, and we don't want to fail ChipID in following check*/ + dwTimes = 0; + break; + } + } + + dwTimes++; + } while ((dwTimes < DOCH_CHIP_ID_TRIALS_FOR_SLAVE)); + + if(dwTimes >= DOCH_CHIP_ID_TRIALS_FOR_SLAVE) /* no more trials..*/ + { /*SLAVE Failed*/ + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("Socket #%d dev1"), socketNo)); + DBG_PRINT_ERR(FLZONE_ATA, " - ChipID FAILED !\r\n"); + rc = DOCH_DiskNotFound; + } + else + { /*SLAVE Succeed*/ + (*bFloorsNum)++; + + DBG_PRINT_FLOW_PRM(FLZONE_ATA, (FLTXT("Socket #%d dev1"), socketNo)); + DBG_PRINT_FLOW(FLZONE_ATA, " - Found ChipID !\r\n"); + /* initialize config registers of floor 1*/ + doch_configFloor(pdev); + + /*Disable interrupts (will be enabled later per API decision)*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CONTROL_REG, DOCH_ATA_NIEN); + } + + } /*SLAVE*/ + +#ifdef FL_UTILS_QUICK_INIT +}/*gDochQuickInit != DOCH_GLOBAL_BOOL_PATTERN*/ +#endif /*FL_UTILS_QUICK_INIT*/ + +#endif /*(ATA_MAX_NUM_OF_DEVICES==2)*/ + + if ((*bFloorsNum)>0 && rc!=DOCH_OK) + { + /* one floor succeed */ + rc = DOCH_OK; + } + /*Reset ATA protocol to ensure device is ready for the next ATA command*/ + /*Waiting to mount to complete before reset protocol*/ + /* need to add delay before reset (another access to DOCH_CONTROL_REG) */ + DOCH_DELAY_BEFORE_ACCESSING_SAME_REGISTER; + + if (pdev->wNumOfDevices == 0) + { + /* during init sequence */ + pdev->wNumOfDevices = (*bFloorsNum); /* needed for reset routine*/ + doch_reset(pdev);/*reset both floors*/ + pdev->wNumOfDevices = 0; /* will be actually updated in init sequence*/ + + }else + { + /* during recover from power loss sequence*/ + if (pdev->wNumOfDevices != *bFloorsNum) + { + /*different number of floors was found*/ + DBG_PRINT_FLOW_PRM(FLZONE_ATA, (FLTXT("originally number of floors was %d and found %d\r\n"), + pdev->wNumOfDevices,*bFloorsNum)); + return DOCH_GeneralFailure; + } + doch_reset(pdev);/*reset both floors*/ + } + return rc; +} + +/****************************************************************************** + * * + * d o c h _ i n i t _ s o c k e t * + * * + * Initialize DOCH socket. * + * * + * Parameters : * + * socketNo : Socket # (0...DOCH_MAX_SOCKETS-1) * + * DOCH_InitSocket : runtime socket init data * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ +DOCH_Error doch_init_socket (FLSNative socketNo, DOCH_InitSocket initSocket) +{ + DOCH_Error rc = DOCH_OK; + DOCH_Socket * pdev; + IOreq ioreq; + register FLSByte i; + FLByte bFloorsNum=0; + + /* args sanity check */ + if ((socketNo < 0) || (socketNo >= DOCH_MAX_SOCKETS)) + return DOCH_BadParameter; + + /*Clear "Ignore Error Bit" indication*/ + gIgnoreErrorBit = 0; + + /*Retreive socket pointer from devices array*/ + pdev = &sockets[socketNo]; + + /*Create a MUTEX for the socket*/ + flCreateMutex(&pdev->mutex); + + /*Clear socket structure*/ + clear_socket(pdev); + + /*Set socket number*/ + pdev->wSocketNo = socketNo; + + /*If no devices found - return failure + If 2 devices - check last partition of device #0 for partition span indication + ============================================================================*/ + DBG_PRINT_FLOW_PRM(FLZONE_ATA, (FLTXT("\nSearching devices on socket #%d...\r\n\n"), socketNo)); + + pdev->wTotalNumOfPartitions = 0; + pdev->nTotalCapacity = 0; + + /*Try identifying device on both 8KB and 128KB memory windows*/ + /*===========================================================*/ + rc = doch_init_window(socketNo,initSocket); + if(rc != DOCH_OK) + { + return rc; + } + + rc = doch_init_floors(pdev,FALSE,&bFloorsNum); + if(rc != DOCH_OK) + { + return rc; + } + + for(i=0; ibAtaDevNum = i; + + tffsset(&ioreq, 0, sizeof(ioreq)); + DOCH_SET_SOCKET_TO_IOREQ_HANDLE(&ioreq, socketNo); + ioreq.irData = &gDiskOnChipDeviceInfo; + /*Identify command with very short timeout, and "option1" on" + (just check if the device responds, not all fields are valid!)*/ + ioreq.irCount = DOCH_IDENTIFY_EXISTANCE; + gUseShortWaitOnBusy = DOCH_SHORT_IDENTIFY_TIMEOUT; + rc = DOCHIdentifyDiskOnChipDeviceSingleFloor(&ioreq); + gUseShortWaitOnBusy = 0; + + /*If the device was NOT identified (e.g. not existing) - + try using ATA standard IDENTIFY DEVICE command*/ + if(rc != DOCH_OK) + { + /*Try Identifying using Standard ATA IDENTIFY DEVICE command*/ + gUseShortWaitOnBusy = DOCH_SHORT_IDENTIFY_TIMEOUT; + rc = doch_ATAstd_IDENTIFY_DEVICE(socketNo, i); + gUseShortWaitOnBusy = 0; + + /*Identifying using Standard ATA IDENTIFY DEVICE command - FAILED*/ + if(rc != DOCH_OK) + { + return DOCH_DiskNotFound; + } + + /*Identifying using Standard ATA IDENTIFY DEVICE command - SUCCEEDED*/ + DBG_PRINT_FLOW_PRM(FLZONE_ATA, (FLTXT("\r\nDev%d identifid WITHOUT ETFFS...\r\n\n"), i)); + } + else + { + /*If the device was WAS identified (e.g. exists) - perform full retrieval of device info data + without "option1" and with a longer timeout*/ + ioreq.irCount = DOCH_IDENTIFY_FROM_FLASH; + gUseShortWaitOnBusy = DOCH_LONG_IDENTIFY_TIMEOUT; + rc = DOCHIdentifyDiskOnChipDeviceSingleFloor(&ioreq); + gUseShortWaitOnBusy = 0; + } + if(rc == DOCH_OK) + pdev->wNumOfDevices ++; +#endif /*CX_TOOLS_SUPPORT*/ + } /* End loop search for number of floors */ + + if(rc != DOCH_OK) + { + return DOCH_DiskNotFound; + } + + pdev->wTotalNumOfPartitions += pdev->device[i].wNumOfPartitions; + pdev->nTotalCapacity += gDiskOnChipDeviceInfo.dwUnformattedCapacity; + + /*Set ATA Device Number back to 0...*/ + pdev->bAtaDevNum = 0; + + DBG_PRINT_FLOW_PRM(FLZONE_ATA, (FLTXT("\r\nFound #%d device(s)...\r\n\n"), pdev->wNumOfDevices)); + + /*Set DPD mode as requested*/ + /*=========================*/ + tffsset(&ioreq, 0, sizeof(ioreq)); + + /*If registered HAL is SPI, disable DPD*/ + if(gAccessLayerType == DOCH_AL_SPI) + { + gDpdSettings.activeMode = DOCH_WM_NORMAL; + gDpdSettings.inActiveMode = DOCH_IM_IDLE; + } + + if(pdev->device[0].ETFFS_Identified) + { + /*1. Set both modes + 2. If DOCH_IM_IDLE_2_DPD configured as Inactive mode, force ETFFS + to enter Inactive mode after the command completes*/ + ioreq.irFlags = DOCH_PM_SET_BOTH_MODES; + if(gDpdSettings.inActiveMode == DOCH_IM_IDLE_2_DPD) + ioreq.irFlags |= DOCH_PM_INACTIVE_MODE; + + /*3. Set Active/Inactive modes*/ + ioreq.irCount = (gDpdSettings.activeMode | gDpdSettings.inActiveMode); + /*4. Set Timeout*/ + ioreq.irLength = gDpdSettings.timeOut; + + /*5. Set Power Modes to device(s) that ETFFS was identified on*/ + /* no need to call flDOCHSetPowerMode twice for each floor - this is done inside flDOCHSetPowerMode*/ + + rc = flDOCHSetPowerMode(&ioreq); + if(rc != DOCH_OK) + return rc; + +#ifdef FL_REPORT_INTERNAL_ERRORS + /* Set DocH to report internal errors*/ + tffsset(&ioreq, 0, sizeof(ioreq)); + ioreq.irCount = DOCH_CP_REPORT_ECC_MODE; + ioreq.irSectorNo = (FLWord)(DOCH_ENABLE_REPORT_ECC_ERRORS); + ioreq.irFlags = DOCH_CUSTOM_PARAM_TEMP; + rc = DOCHSetCustomParameter(&ioreq); + if(rc != DOCH_OK) + { + DBG_PRINT_WRN_PRM(FLZONE_ATA, (FLTXT("\r\nWARNING: Failed setting mDoc to report internal errors with status %d \r\n"), rc)); + /*return rc;*/ /*do not fail - backward compatibility*/ + } +#endif /*FL_REPORT_INTERNAL_ERRORS*/ + + } + + return DOCH_OK; +} + + + +/*********************************************************/ +/* Function name : doch_release_socket*/ +/* Description : calls to appropriated function */ +/* to release all allocated memory / devices etc */ +/* Return type : DOCH_Error */ +/* Argument : int socketNo*/ +/*********************************************************/ +DOCH_Error doch_release_socket( int socketNo ) +{ +#ifdef DOCH_USE_FUNC + DOCH_Error status; + DOCH_Socket* pdev; + + if(socketNo > DOCH_MAX_SOCKETS - 1) + return DOCH_BadParameter; + + pdev = &sockets[socketNo]; + + /* Un-register the socket */ + status = (DOCH_Error)(pdev->halRoutines.hal_doch_release(socketNo)); + + /*Delete the mutex*/ + flDeleteMutex(&pdev->mutex); + + if(status != DOCH_OK) + return DOCH_GeneralFailure; +#endif /*DOCH_USE_FUNC*/ + + return DOCH_OK; +}/*doch_release_socket()*/ + + + + +/****************************************************************************** + * * + * d o c h _ g e t _ d i s k * + * * + * Return pointer to device, by device number. * + * * + * Parameters : * + * socketNo : Socket # (0...DOCH_MAX_SOCKETS-1) * + * devNum : Device # (0,1) * + * * + * Returns : * + * Pointer to DOCH structure. * + * * + ******************************************************************************/ +DOCH* DOCH_get_disk(FLSNative socketNo, FLSNative devNum) +{ + if(socketNo > (DOCH_MAX_SOCKETS-1)) + return NULL; + else + return &sockets[socketNo].device[devNum]; +} + +/****************************************************************************** + * * + * d o c h _ s e t T r a n s f e r M o d e * + * * + * Sets data transfer mode * + * * + * Parameters : * + * socketNo : Socket # (0...DOCH_MAX_SOCKETS-1) * + * devNum : ATA Device [0..1] * + * tm : required data transfer mode: * + * DOCH_DATA_MODE_SINGLE * + * DOCH_DATA_MODE_MULT * + * * + * Returns : * + * Pointer to DOCH structure. * + * * + ******************************************************************************/ +DOCH_Error doch_setTransferMode (FLSNative socketNo, FLSNative devNum, DOCH_TransferMode tm, FLDword drqSize) +{ + if(socketNo > (DOCH_MAX_SOCKETS-1)) + return DOCH_BadParameter; + else + { + sockets[socketNo].device[devNum].dataTransferMode = tm; + sockets[socketNo].device[devNum].dwMulti_Current = drqSize; + + } + + return DOCH_OK; +} + +/****************************************************************************** + * * + * d o c h _ g e t T r a n s f e r M o d e * + * * + * Returns data transfer mode * + * * + * Parameters : * + * socketNo : Socket # (0...DOCH_MAX_SOCKETS-1) * + * * + * Returns : * + * Pointer to DOCH structure. * + * * + ******************************************************************************/ +DOCH_TransferMode doch_getTransferMode (FLSNative socketNo, FLSNative devNum) +{ + return sockets[socketNo].device[devNum].dataTransferMode; +} + +/****************************************************************************** + * * + * d o c h _ s e t C o n f i g R e g 1 6 * + * * + * Set DOCH 16Bit configuration register * + * Register values are maintained by a global structure of type * + * DOCH_ConfigRegsValue in order to allow recovery after power loss. * + * * + * Parameters : * + * pdev : device descriptor * + * registerOffset: Register offset * + * registerValue : Register Value * + * * + * Returns : * + * Pointer to DOCH structure. * + * * + ******************************************************************************/ +DOCH_Error doch_setConfigReg16(DOCH_Socket* pdev, FLDword registerOffset, FLNative registerValue) +{ + + if(registerOffset == (FLDword)HIB_BURST_WRITE_MODE_CTRL_REG) + { + configRegValue.wBurstWriteModeCtrl |= registerValue; + configRegValueSet.wBurstWriteModeCtrlSet = TRUE; + } + else if(registerOffset == (FLDword)HIB_BURST_READ_MODE_CTRL_REG) + { + configRegValue.wBurstReadModeCtrl |= registerValue; + configRegValueSet.wBurstReadModeCtrlSet = TRUE; + } + else if(registerOffset == (FLDword)HIB_IPL_CONTROL_REG) + { + configRegValue.wIPLCtrl |= (registerValue | DOCH_IPL_WRITE_READY); + configRegValueSet.wIPLCtrlSet = TRUE; + } + else if(registerOffset == (FLDword)HIB_POWER_DOWN_REG) + { + configRegValue.wPowerDown |= registerValue; + configRegValueSet.wPowerDownSet = TRUE; + } + else if(registerOffset == (FLDword)HIB_DMA_CTRL_REG) + { + configRegValue.wDMACtrl |= registerValue; + configRegValueSet.wDMACtrlSet = TRUE; + } + else if(registerOffset == (FLDword)HIB_SW_LOCK_REG) + { + configRegValue.wSWLock |= registerValue; + configRegValueSet.wSWLockSet = TRUE; + } + else if(registerOffset == (FLDword)HIB_ENDIAN_CTRL_REG) + { + configRegValue.wEndianCtrl |= registerValue; + configRegValueSet.wEndianCtrlSet = TRUE; + } + else if(registerOffset == (FLDword)HIB_DMA_NEGATION_REG) + { + configRegValue.wEndianNegation |= registerValue; + configRegValueSet.wEndianNegationSet = TRUE; + } + else if(registerOffset == (FLDword)HIB_OPERATION_MODE_REG) + { + configRegValue.wOperationMode |= registerValue; + configRegValueSet.wOperationModeSet = TRUE; + } + else if(registerOffset == (FLDword)HIB_POWER_MODE_REG) + { + /*Do nothing*/ + } + else + { + return DOCH_BadParameter; + } + + DOCHWRITE_CTRL_REG (pdev->bRegBase, registerOffset, registerValue); + + return DOCH_OK; +} + +/****************************************************************************** + * * + * d o c h _ g e t C o n f i g R e g 1 6 * + * * + * Returns DOCH 16Bit configuration register value * + * * + * Parameters : * + * pdev : device descriptor * + * registerOffset: Register offset * + * * + * Returns : * + * Pointer to DOCH structure. * + * * + ******************************************************************************/ +FLWord doch_getConfigReg16(DOCH_Socket* pdev, FLSNative registerOffset) +{ + /*Read 16Bit register*/ + return DOCHREAD_CTRL_REG(pdev->bRegBase, registerOffset); +} + + + +/****************************************************************************** + * * + * d e f _ d o c h D e l a y U s e c * + * * + * default implementation of delay according to access time * + * * + * Parameters : * + * FLDword usec: time to wait in uSec * + * dwAccessTime: access time in nano sec * + * * + * Returns : * + * 0 on success, otherwise error number. * + * * + ******************************************************************************/ +DOCH_Error def_dochDelayUsec(FLDword usec,FLDword dwAccessTime) +{ + volatile FLWord val; + FLDword dwCount = usec * (1000UL / dwAccessTime); +#ifdef DOCH_USE_FUNC + DOCH_Socket * pdev =&sockets[0]; +#endif /*DOCH_USE_FUNC*/ + + if (dwCount==0) + dwCount=1; + + /* read any register dwCount times; each time consumes gDochAccessNanosec*/ + while (dwCount-- > 0) + { + +#ifdef DOCH_USE_FUNC + val = DOCHREAD_CTRL_REG(pdev->bRegBase, HIB_CHIPID1_REG); +#else /*DOCH_USE_FUNC*/ + val = DOCHREAD_CTRL_REG(sockets[0].bRegBase, HIB_CHIPID1_REG); +#endif /*DOCH_USE_FUNC*/ + + } + + return DOCH_OK; + +} + + +#ifdef __cplusplus +} + +#endif diff -urN linux-2.6.30.4-orig/drivers/block/tffs/doch_ata.h linux-2.6.30.4/drivers/block/tffs/doch_ata.h --- linux-2.6.30.4-orig/drivers/block/tffs/doch_ata.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/doch_ata.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,737 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/***********************************************************************************/ +/* */ +/* Header file for doch_ata module */ +/* */ +/***********************************************************************************/ + +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Test for 7.x/src/H3/doch_ata.h-arc $ + * + * Rev 1.46 Mar 17 2008 13:05:36 einat.avidan + * update mount timeout + * + * Rev 1.45 Mar 09 2008 17:12:52 Yuli.Izrailov + * Set DOCH_MOUNT_WAIT to 6000 + * + * Rev 1.44 Dec 26 2007 10:13:36 einat.avidan + * doch_reset and doch_init_floors - changed parameters. + * + * Rev 1.43 Dec 11 2007 12:29:14 einat.avidan + * init sequence and DOCHConfigHW: change parameters of internal functions + * + * Rev 1.42 Dec 04 2007 17:32:42 einat.avidan + * Define max mount time + * def_dochDelayUsec - receives new parameter: access time. + * New functions declaration: doch_init_floor and doch_configCommon + * + * Rev 1.41 Oct 30 2007 17:01:42 einat.avidan + * replace dochEnableATAInterrupt function with macros + * + * Rev 1.40 Oct 23 2007 15:37:44 einat.avidan + * before reset wait for the longest operation to complete. + * + * Rev 1.39 Oct 23 2007 12:27:54 einat.avidan + * optimization: delay after setting head register only + * when switching floors + * + * Rev 1.38 Oct 22 2007 11:34:50 einat.avidan + * update copyrights header + * + * Rev 1.37 Oct 21 2007 15:29:34 einat.avidan + * fix compilation warnings + * + * Rev 1.36 Oct 11 2007 18:48:42 Einat.Avidan + * update DOCH_VERY_LONG_WAIT + * in every write to drive head register set LBA bit. + * doch_reset resets both floor (no need of devNum parameter) + * caller responsible to set device head register + * when calling to dochEnableATAInterrupt (no need of devNum parameter) + * new function def_dochDelayUsec + * add compilation flags for SOTP and SLPP + * + * Rev 1.35 Sep 04 2007 15:40:28 einat.avidan + * bug fix: DOCH_VERY_LONG_WAIT definition was added + * (add_partition and secure_erase should have long waiting time) + * + * Rev 1.34 Mar 13 2007 13:47:20 einat.avidan + * add support for SLPP + * + * Rev 1.33 Feb 28 2007 09:58:42 einat.avidan + * No change + * + * Rev 1.32.1.1 Nov 12 2006 09:47:02 Yaniv.Iarovici + * 1. Added parameter 'FLBoolean waitOnBusy' to doch_reset(). + * 2. Added 'DOCH_SRST_WAIT' + * + * Rev 1.32.1.0 Oct 31 2006 12:23:36 yaniv.iarovici + * Added doch_init_window(). + * + * Rev 1.32 Oct 05 2006 11:00:42 yaniv.iarovici + * 1. Removed dwMulti_Read, dwMulti_Write. + * 2. Added dwMulti_MAX. + * 3. Removed DOCH_multReadOp structure. + * + * Rev 1.31 Sep 11 2006 13:45:16 yaniv.iarovici + * Legal header added + * + * Rev 1.30 Aug 22 2006 13:23:54 Yaniv.Iarovici + * Add 'extern "c"' on flExit() definition + * - extern DOCH_Socket sockets [DOCH_MAX_SOCKETS] + * - DOCH_get_socket MACRO definition + * + * Rev 1.29 Aug 16 2006 08:46:10 Yaniv.Iarovici + * structure DOCH: + * - Remove wOtpToParition[] + * - Add ETFFS_Identified instead + * + * Rev 1.28 Aug 09 2006 17:26:54 Polina.Marimont + * initial for DOC Driver 1.0 + * + */ + +#ifndef DOCH_ATA_H +#define DOCH_ATA_H + +#include "doch_sys.h" +#include "doch_api.h" + +#include "part_inf.h" + +/* + * macros + * (also customizable for internal purpose) + * + */ + +/* 'long' DOCH operations can take up to DOCH_LONG_WAIT milliseconds */ +#ifndef DOCH_LONG_WAIT + #define DOCH_LONG_WAIT 500 +#endif /*DOCH_LONG_WAIT*/ + +/* 'short' DOCH operations can take up to DOCH_SHORT_WAIT milliseconds */ +#ifndef DOCH_SHORT_WAIT + #define DOCH_SHORT_WAIT 450 +#endif /*DOCH_SHORT_WAIT*/ + +/* 'very long' DOCH operations can take up to DOCH_VERY_LONG_WAIT milliseconds */ +#ifndef DOCH_VERY_LONG_WAIT + #define DOCH_VERY_LONG_WAIT 180000 +#endif /*DOCH_VERY_LONG_WAIT*/ + +/* Wait for busy bit to clear before sending SRST to the device (milliseconds) */ +#ifndef DOCH_SRST_WAIT + #define DOCH_SRST_WAIT DOCH_SHORT_WAIT +#endif /*DOCH_SRST_WAIT*/ + +/* Wait for busy bit to clear during init sequence(milliseconds) */ +#ifndef DOCH_MOUNT_WAIT + #define DOCH_MOUNT_WAIT 10000 +#endif /*DOCH_SRST_WAIT*/ + +/* "Very short wait" used for identifying device = 50ms */ +#ifndef DOCH_SHORT_IDENTIFY_TIMEOUT + #define DOCH_SHORT_IDENTIFY_TIMEOUT (10L*1000000L/gDochAccessNanosec) +#endif /*DOCH_SHORT_IDENTIFY_TIMEOUT*/ + +/* "Longer" wait used for identifying device = 500ms */ +#ifndef DOCH_LONG_IDENTIFY_TIMEOUT + #define DOCH_LONG_IDENTIFY_TIMEOUT (500L*1000000L/gDochAccessNanosec) +#endif /*DOCH_LONG_IDENTIFY_TIMEOUT*/ + +#ifndef DOCH_DEFAULT_SLEEP_PERIOD + #define DOCH_DEFAULT_SLEEP_PERIOD 3000 +#endif /* DOCH_DEFAULT_SLEEP_PERIOD */ + +/*#define ONE_SEC_IN_NANO_SEC (1000000000 / gDochAccessNanosec)*/ + +/* maximum number of sectors which could be read from / written to DOCH at once */ +#define DOCH_MAX_SECTORS 256 + +/*ATA device definitions*/ +#define DOCH_ATA_MASTER_DEV 0 /* master device only */ +#define DOCH_ATA_SLAVE_DEV 1 /* slave device only */ +#define DOCH_ATA_ALL_DEVS 0xff /* all devices */ + +#define ATA_NO_ERR 0 /* no error on ATA command */ + +#define DOCH_ATA_MAX_TIMEOUT 0xFFFFFFFF + +/* Access Layer Types */ +typedef enum { + DOCH_AL_NONE = 0xCAF0, + DOCH_AL_NOR = 0xCAF1, + DOCH_AL_SPI = 0xCAF2, + DOCH_AL_USER = 0xCAF3, + DOCH_AL_SIM = 0xCAF4 +} DOCH_AccessLayerType; + +/* Optional bits in DOCH_DRIVE_HEAD_REG */ +#define DRIVE_HEAD_OPT1 0x80 +#define DRIVE_HEAD_OPT2 0x20 + +/* Pattern to add to DOCH_DRIVE_HEAD_REG to */ +/*Option1*/ +#define CUSTOM_PARAM_TEMP DRIVE_HEAD_OPT1 /*Temporary value*/ +#define CUSTOM_PARAM_DEFAULT 0 /*DEFAULT value*/ +#define PERM_DEFAULT_PART_OP DRIVE_HEAD_OPT1 /*Permanently set default partition number*/ +#define PREPARE_FOR_WRITE_OP 0 +#define REWRITE_NORMAL_OP DRIVE_HEAD_OPT1 +#define WRITE_NORMAL_OP DRIVE_HEAD_OPT1 +#define HASH_AS_IS 0 +#define HASH_BY_KEY DRIVE_HEAD_OPT1 +#define DELETE_PARTITIONS_FAST 0 +#define DELETE_PARTITIONS_COMPLETE DRIVE_HEAD_OPT1 +/*Option2*/ +#define ERASE_NORMAL 0 +#define ERASE_IMMEDIATE DRIVE_HEAD_OPT2 + + +typedef enum { DOCH_4BITS = 0, /*TBD*/ + DOCH_ATA_NIEN = 2, + DOCH_ATA_SRST = 4 +} DOCH_control_reg; + +/* Data transfer modes */ +typedef enum { DOCH_DATA_MODE_SINGLE = 0x00, + DOCH_DATA_MODE_MULT = 0x01 +} DOCH_TransferMode; + +/* Atomic write sequence control */ +typedef enum { DOCH_START_ATOMIC_WRITE = 0x00, + DOCH_FINISH_ATOMIC_WRITE = 0x01, + DOCH_ABORT_ATOMIC_WRITE = 0x02 +} DOCH_AtomicSeqCtrl; + +/* set of DOCH Vendor-Specific ATA Commands */ +typedef enum { + /*I/O*/ + DOCH_VSCMD_READ_PARTITION = 0x82, + DOCH_VSCMD_WRITE_PARTITION = 0x83, + DOCH_VSCMD_WRITE_FLEXI = 0x84, + + /*Sectors Operations*/ + DOCH_VSCMD_OPTIMIZE_PARTITION_SECTORS = 0x86, + DOCH_VSCMD_ERASE_PARTITION_SECTORS = 0x88, + + /*Hash*/ + DOCH_VSCMD_READ_CALCULATED_HASH = 0x8A, + DOCH_VSCMD_WRITE_CALCULATED_HASH = 0x8B, + DOCH_VSCMD_READ_ORIGINAL_HASH = 0x8C, + DOCH_VSCMD_WRITE_GIVEN_HASH = 0x8D, + + /*Sub-commanded commands*/ + DOCH_VSCMD_PARTITION_MANAGEMENT = 0xFA, + DOCH_VSCMD_ACCESS_CONTROL = 0xFB, + DOCH_VSCMD_EXT_DEVICE_CTRL = 0xFC, + DOCH_VSCMD_EXT_SECURITY_CTRL = 0xFD, + + /*Supported standard ATA commands*/ + DOCH_CMD_IDENTIFY_DEV = 0xEC, + DOCH_DOWNLOAD_MICROCODE = 0x92 + +} DOCH_Command; + +/* set of operation codes for DOCH_VSCMD_PARTITION_MANAGEMENT command */ +typedef enum { + DOCH_GET_PARTITION_INFO = 0x00, + DOCH_SET_DEFAULT_PARTITION = 0x11, + DOCH_SET_PARTITION_PROTECTION = 0x18, + DOCH_GET_PARTITION_USER_ATTR = 0x70, + DOCH_SET_PARTITION_USER_ATTR = 0x71, + DOCH_DELETE_PARTITIONS = 0xB0, + DOCH_ADD_PARTITION = 0xB4, + DOCH_SECURE_ERASE = 0xB8 +} DOCH_PartitionManageOp; + +/* set of operation codes for DOCH_VSCMD_ACCESS_CONTROL command */ +typedef enum { + DOCH_EN_ACCESS_WPWD = 0x30, + DOCH_DISABLE_ACCESS = 0x31, + + /*Enable access with challange/response protocol*/ + DOCH_TX_HOST_PUBLICKEY = 0x32, + DOCH_RX_DOCH_PUBLICKEY = 0x33, +#ifndef FL_SLPP + DOCH_VERIFY_HOST_KEY = 0x34 +#else/* FL_SLPP */ + DOCH_VERIFY_HOST_KEY = 0x34, + /*SLPP Specific*/ + DOCH_SLPP_UNLOCK_RANGE = 0x40, + DOCH_SLPP_UNLOCK_ENTIRE_PARTITION = 0x41, + DOCH_SLPP_LOCK_RANGE = 0x42, + DOCH_SLPP_STICKY_LOCK_RANGE = 0x43, + DOCH_SLPP_REPORT_LOCKED_RANGES = 0x44 +#endif /*FL_SLPP*/ +} DOCH_AccessCtrlOp; + +/* set of operation codes for DOCH_VSCMD_EXT_DEVICE_CTRL command */ +typedef enum { + DOCH_IDENTIFY_DISKONCHIP_DEVICE = 0x00, + DOCH_GET_EXTENDED_DEVICE_INFO = 0x01, + DOCH_SET_DATA_XFER_MODE = 0x10, + DOCH_ATOMIC_WRITE_SEQUENCE = 0x20, + DOCH_OPTIMIZE_MEDIA = 0x30, + DOCH_GET_CUSTOM_PARAM = 0x40, + DOCH_SET_CUSTOM_PARAM = 0x41, + DOCH_CALIBRATE_CLOCK = 0x50, + DOCH_GET_POWER_MODE = 0x60, + DOCH_SET_POWER_MODE = 0x61, + DOCH_GET_DISK_USER_ATTR = 0x70, + DOCH_SET_DISK_USER_ATTR = 0x71, + DOCH_GET_CONFIGURATION_DATA = 0x72, + DOCH_SET_CONFIGURATION_DATA = 0x73, + DOCH_ACTIVATE_DEBUG_MODE = 0x7C, + DOCH_RETRIEVE_DBG_MSG = 0x7E, + DOCH_SET_ALERT_LEVEL = 0x7F, + DOCH_GET_RESET_STATUS = 0x80, + DOCH_NOTIFY_PLATFORM_RESUMED = 0x8E, + DOCH_NOTIFY_RESET = 0x8F +} DOCH_DeviceCtrlOp; + +/* set of operation codes for DOCH_VSCMD_EXT_SECURITY_CTRL command */ +typedef enum { + DOCH_REPORT_SUPPORTED_ALGORITHMS = 0x00, + DOCH_GET_ALGORITHM_CAPABILITIES = 0x01, + DOCH_SET_ALGORITHM_MODE = 0x02, + DOCH_RETURN_RANDOM_NUMBERS = 0x10, + DOCH_AUTO_HASH_CONTROL = 0x40, + DOCH_SET_KEYS = 0x48, + DOCH_START_HASH_STREAM_CALC = 0x50, + DOCH_READ_STOP_HASH_STREAM_CALC = 0x51 +} DOCH_SecurityCtrlOp; + +/* set of operation codes for DOCH_VSCMD_CRYPTO_CONTROL command */ +typedef enum { DOCH_HASH_NO_ENCRYPTION = 0x00, + DOCH_HASH_ENCRYPT_BY_KEY = 0x01 +} DOCH_HashEncrypt_Op; + +/* bits in DOCH_STATUS_REG and DOCH_ALT_STATUS_REG registers */ +#define DOCH_ERROR 0x01 +#define DOCH_DRQ 0x08 +#define DOCH_DSC 0x10 +#define DOCH_READY 0x40 +#define DOCH_BUSY 0x80 + +/* bits in DOCH_STATUS_REG and DOCH_ALT_STATUS_REG registers */ +#define DOCH_ERR_REG_BIT0 0x01; +#define DOCH_ERR_REG_BIT1 0x02; +#define DOCH_ERR_REG_ABRT 0x04; +#define DOCH_ERR_REG_BIT3 0x08; +#define DOCH_ERR_REG_BIT4 0x10; +#define DOCH_ERR_REG_BIT5 0x20; +#define DOCH_ERR_REG_BIT6 0x40; +#define DOCH_ERR_REG_BIT7 0x80; + +/* bits for DOCH_DRIVE_HEAD_REG register */ +#define DOCH_DEVICE 0x10 +#define DOCH_LBA 0x40 +#define DOCH_DRIVE_HEAD 0xA0 + +#define DOCH_SELECT_DEV0 DOCH_LBA +#define DOCH_SELECT_DEV1 (DOCH_DEVICE|DOCH_LBA) +#define DOCH_SELECT_DEV(devNum) ((devNum*DOCH_DEVICE)|DOCH_LBA) + +/* DOCH configuration bits (IDENTIFY_DEVICE Word#0) */ +#define DOCH_ATAPI 0x8000 +#define DOCH_REMOVABLE 0x0080 +#define DOCH_FIXED 0x0040 + +/* IDENTIFY DEVICE data */ +/*==========================*/ +typedef struct { + FLWord wGeneralConfiguration; + FLWord wDefaultNumberOfCylinders; /*1*/ + FLWord wSpecificConfiguration; /*ATA-5*/ + FLWord wDefaultNumberOfHeads; /*3*/ + FLDword dwReserved2; + FLWord wDefaultSectorsPerTrack; /*6*/ + FLWord wReserved1[3]; + FLByte bSerialNumber[20]; /*10*/ + FLWord wReserved4[2]; + FLWord wVsFLBytesInReadWriteLONG; /*obsolete in ata-5*/ + FLByte bFirmwareRevision[8]; /*23*/ + FLByte bModelNumber[40]; /*27*/ + + FLByte bReserved3; /*47 ata-4+ : must be 0x80*/ + FLByte bMaxSectorsPerMulti; + + FLWord wReserved5; + FLWord wCapabilities; /*49*/ + FLWord wCapabilities2; /*ata-4*/ + + FLByte bPIOTransferTiming; /*51 obsolete in ATA-5*/ + FLByte bReserved6a; + + FLWord wReserved7; /*was (single-word?) DMA Timing in ATA-2*/ + FLWord wWordSupported; /*53*/ + FLWord wCurrentNumberOfCylinders; /*54*/ + FLWord wCurrentNumberOfHeads; /*55*/ + FLWord wCurrentSectorPerTrack; /*56*/ + + FLWord wCurrentCapacityInSectorsLow; /*57*/ + FLWord wCurrentCapacityInSectorsHigh; /*58*/ + + FLByte bMultipleSectorSettingValid; /*59*/ + FLByte bMultipleSectorCurrentNumber; + + FLWord wTotalNumberOfSectorsLow; /*60*/ + FLWord wTotalNumberOfSectorsHigh; /*61*/ + + FLWord wReserved8; /*was singlewordDMASelect+Support in ATA-2*/ + + FLByte bMultiwordDMASelected; /*63*/ + FLByte bMultiwordDMASupported; + + FLByte bReserved9; /*64*/ + FLByte bAdvancedPIOsupported; + + FLWord wMinDMACycleTimePerWord; + FLWord wRecommndedMinDMACycleTimePerWord; + FLWord wMinPIOCycleTimeWithoutFlowControl; + FLWord wMinPIOCycleTimeWithIORDY; + FLWord wReserved10[6]; + + FLWord wQueueDepth; /*75 ata-4*/ + FLWord wReserved11[4]; + + FLWord wMajorVersionNumber; /*80*/ + FLWord wMinorVersionNumber; + FLWord wCommandSetsupported1; /*82*/ + FLWord wCommandSetsupported2; + + FLWord wCommandSetFeatureExtension; /*84 ata-4*/ + FLWord wCommandSetFeatureEnabled1; /*ata-4*/ + FLWord wCommandSetFeatureEnabled2; /*86 ata-4*/ + FLWord wCommandSetFeatureDefault; /*ata-4*/ + + FLByte bUltraDMASelected; /*88 ata-4*/ + FLByte bUltraDMASupported; + + FLWord wTimeForSecurityEraseCompletion; /*ata-4*/ + FLWord wTimeForEnhancedSecurityEraseCompletion; /*90 ata-4*/ + + FLWord wCurrentAdvancedPowerManagementValue; /*ata-4*/ + + FLWord wMasterPasswordRevision; /*92 ata-5*/ + FLWord wHardwareResetResult; /*ata-5*/ + + FLWord wReserved12[33]; + + FLWord wRemovableMediaNotificationSupport; /*127 ata-4*/ + + FLWord wSecurityStatus; /*128, i.e. 127 words left*/ + FLWord wVendorSpecific[31]; /*129-159*/ + FLWord wCFApowermode1; + FLWord wCFAreserved[15]; + FLWord wCurrentMediaSerialNumber[30]; + + FLWord wReserved13[49]; + + FLWord wIntegrityWord; +} DOCH_DriveParameters; + +typedef struct { + FLSDword activeMode; + FLSDword inActiveMode; + FLSDword timeOut; +} DOCH_DpdSettings; + + +/*IDENTIFY DEVICE information bits*/ +/*================================*/ + +/*for generalConfiguration*/ +#define GENERAL_CONFIG_ATAPI 0x8000 /*otherwise ATA*/ +#define GENERAL_CONFIG_REMOVABLE_MEDIA 0x80 /*otherwise not*/ +#define GENERAL_CONFIG_NON_REMOVABLE_DRIVE 0x40 /*and/or device*/ +#define GENERAL_CONFIG_RESPONSE_INCOMPLETE 0x04 /*ATA-5*/ + +/*for specificConfiguration*/ +#define DEVICE_REQUIRES_SET_FEATURES_ID_INCOMPLETE 0x37C8 +#define DEVICE_REQUIRES_SET_FEATURES_ID_COMPLETE 0x738C +#define DEVICE_NOT_REQUIRE_SET_FEATURES_ID_INCOMPLETE 0x8C73 +#define DEVICE_NOT_REQUIRE_SET_FEATURES_ID_COMPLETE 0xC837 + +/*for capabilities*/ +#define CAPABILITY_STANDBY_TIMER_AS_IN_STANDARD 0x2000 /*1<<13*/ +#define CAPABILITY_IORDY_SUPPORTED 0x0800 /*1<<11*/ +#define CAPABILITY_IORDY_CAN_BE_DISABLED 0x0400 /*1<<10*/ +#define CAPABILITY_MUST 0x0300 /*just must be*/ + +/*for capabilities2*/ +#define CAPABILITY2_MUST 0x4000 +#define CAPABILITY2_DEVICE_HAS_STANDBY_TIMER_MINIMUM 0x0001 + +/*for wordSupported*/ +#define FIELDS54_58_VALID 1 /*geometry*/ +#define FIELDS64_70_VALID 2 /*timing*/ +#define FIELD88_VALID 4 /*ATA-4: Ultra-DMA modes*/ + +/*for multipleSectorSetting*/ +/*#define MULTI_SECTOR_SETTING_CORRECT 0x100*/ + +/*for multiwordDma*/ +#define MULTI_WORD_DMA_0 1 +#define MULTI_WORD_DMA_1 2 +#define MULTI_WORD_DMA_2 4 /*ATA-4*/ +/*dma 'selected' - one bit*/ +/*dma 'supported' - also one bit, but with ATA-4/5 it MUST support*/ +/*all modes below. AND must have their bits in 1 too.*/ + +/*for advancedPIOsupported; 1 for pio3 3 for pio4*/ +#define ADVANCED_PIO_3_SUPPORTED 1 +#define ADVANCED_PIO_4_SUPPORTED 2 + + +/*for majorVersionNumber*/ +#define SUPPORTS_ATA_1 2 +#define SUPPORTS_ATA_2 4 +#define SUPPORTS_ATA_3 8 +#define SUPPORTS_ATA_4 0x10 +#define SUPPORTS_ATA_5 0x20 + +/*for minorVersionNumber*/ +#define ATA3_PUBLISHED 0x0A +#define ATA_ATAPI4_PUBLISHED 0x12 +#define ATA_ATAPI5_PUBLISHED 0x18 +/*#error download last draft & find out!*/ + +/*for commandSetsupported1, commandSetFeatureEnabled1*/ +#define SUPPORTS1_SMART 0x01 +#define SUPPORTS1_SECURITY 0x02 +#define SUPPORTS1_REMOVABLE 0x04 +#define SUPPORTS1_POWER_MANAGEMENT 0x08 +#define SUPPORTS1_PACKET_COMMAND 0x10 /*ATA-4. ATA-5: must be zero*/ +#define SUPPORTS1_WRITE_CACHE 0x20 /*ATA-4*/ +#define SUPPORTS1_LOOK_AHEAD 0x40 /*ATA-4*/ +#define SUPPORTS1_RELEASE_INTERRUPT 0x80 /*ATA-4*/ +#define SUPPORTS1_SERVICE_INTERRUPT 0x100 /*ATA-4*/ +#define SUPPORTS1_DEVICE_RESET_CMD 0x200 /*ATA-4*/ +#define SUPPORTS1_HOST_PROTECTED_AREA_FEATURE 0x400 /*ATA-4*/ +#define SUPPORTS1_WRITE_BUFFER 0x1000 /*ATA-4*/ +#define SUPPORTS1_READ_BUFFER 0x2000 /*ATA-4*/ +#define SUPPORTS1_NOP 0x4000 /*ATA-4*/ +/*1<<11 obsolete*/ +/*1<<15 obsolete*/ + +/*for commandSetsupported2, commandSetFeatureEnabled2*/ +#define SUPPORTS2_MUST 0x4000 +#define SUPPORTS2_DOWNLOAD_MICROCODE 0x01 /*ATA-4*/ +#define SUPPORTS2_READ_WRITE_DMA_QUEUED 0x02 /*ATA-4*/ +#define SUPPORTS2_CFA_FEATURE 0x04 /*ATA-4*/ +#define SUPPORTS2_ADVANCED_POWER_MANAGEMENT 0x08 /*ATA-4*/ +#define SUPPORTS2_REMOVABLE_MEDIA_NOTIFICATION 0x10 /*ATA-4*/ +#define SUPPORTS2_POWERUP_IN_STANDBY 0x20 /*ATA-5*/ +#define SUPPORTS2_NEEDS_SET_FEATURES_TO_SPIN 0x40 /*ATA-5*/ +#define SUPPORTS2_ADDRESS_OFFSET_RESERVED_BOOT 0x80 /*ATA-5*/ +#define SUPPORTS2_SET_MAX_SECURITY_EXTENSION 0x100 /*ATA-5*/ + +/*for commandSetFeatureExtension, commandSetFeatureDefault*/ +#define CMDSET_EXTENSION_MUST 0x4000 + +/*for ultraDma*/ +#define ULTRA_DMA_0 1 +#define ULTRA_DMA_1 2 +#define ULTRA_DMA_2 4 +#define ULTRA_DMA_3 8 /*ATA-5*/ +#define ULTRA_DMA_4 0x10 /*ATA-5*/ +/*selected: one, supported: one and below*/ + +/*for hardwareResetResult (ATA-5)*/ +#define HARDRESET_RESULT_MUST 0x4101 + +#define HARDRESET_CBLID_ABOVE_VIH 0x2000 + +#define HARDRESET_DEVICE_0_JUMPER 0x02 +#define HARDRESET_DEVICE_0_CSEL 0x04 +#define HARDRESET_DEVICE_0_OTHER 0x06 + +#define HARDRESET_DEVICE_0_PASSED_DIAGNOSTICS 0x08 +#define HARDRESET_DEVICE_0_DETECTED_PDIAG 0x10 +#define HARDRESET_DEVICE_0_DETECTED_DASP 0x20 +#define HARDRESET_DEVICE_0_RESPONDS_FOR_1 0x40 + +#define HARDRESET_DEVICE_1_JUMPER 0x200 +#define HARDRESET_DEVICE_1_CSEL 0x400 +#define HARDRESET_DEVICE_1_OTHER 0x600 + +#define HARDRESET_DEVICE_1_ASSERTED_PDIAG 0x800 + +/*for removableMediaNotificationSupport*/ +#define REMOVABLE_MEDIA_STATUS_NOTIFICATION_SUPPORTED 1 + +/*for securityStatus*/ +#define SECURITY_MAXIMUM 0x100 /*otherwise HIGH*/ +#define SECURITY_ENCHANCED_ERASE_SUPPORTED 0x20 /*ATA-4*/ +#define SECURITY_COUNT_EXPIRED 0x10 +#define SECURITY_FROZEN 0x08 +#define SECURITY_LOCKED 0x04 +#define SECURITY_ENABLED 0x02 +#define SECURITY_SUPPORTED 0x01 + +typedef struct { + FLByte bReserved[0x200]; +} DOCH_DeviceAttributes; + +/* long-word-aligned buffer */ +typedef union { unsigned char cbuf [DOCH_SECTOR_SIZE]; + unsigned short sbuf [DOCH_SECTOR_SIZE / sizeof(short)]; + unsigned long lbuf [DOCH_SECTOR_SIZE / sizeof(long)]; +} DOCH_Buf; + +#define DOCH_CHIP_ID_H3 0x4833 +#define DOCH_CHIP_ID_H4 0x4834 +#define DOCH_CHIP_ID_H5 0x4835 + +/* Runtime configuration flags*/ +/*DOCH Flags Offsets*/ +#define DOCH_FLAGSO_USE_CHS 0 +#define DOCH_FLAGSO_USE_DMA_READ 1 +#define DOCH_FLAGSO_USE_DMA_WRITE 2 +#define DOCH_FLAGSO_USE_INTERRUPT 3 + +/*DOCH Flags Bits*/ +#define DOCH_FLAGSB_USE_CHS 0x00000001 /* use Cyl/Head/Sector block addressing */ +#define DOCH_FLAGSB_USE_DMA_READ 0x00000002 /* use h/w DMA when reading sectors */ +#define DOCH_FLAGSB_USE_DMA_WRITE 0x00000004 /* use h/w DMA when writing sectors */ +#define DOCH_FLAGSB_USE_INTERRUPT 0x00000008 /* use DOCH interrupt */ + +/* single DOCH device */ +typedef struct { + DOCH_DriveParameters driveParameters; /* ATA::IDENTIFY DEVICE data */ + FLWord wNumOfPartitions; + FLWord ETFFS_Identified; /*ETFFS exists on device*/ + FLDword flags; + FLDword dwMulti_MAX; + FLDword dwSpare1; + FLDword dwMulti_Current; + DOCH_TransferMode dataTransferMode; +} DOCH; + +typedef struct { + volatile FLByte * bRegBase; + FLByte bAtaDevNum; /* Indicates which ATA device to send command to (0..1)*/ +#ifdef DOCH_NO_SUPPORT_PARALLEL_SDK_INSTANCES + FLByte bLastDevNum; /* Indicates which ATA device was recently accessed */ +#endif /*DOCH_NO_SUPPORT_PARALLEL_SDK_INSTANCES*/ + FLDword dwPhysicalAddress; /* NOT USED, returned by the SDK by a specific API */ + FLWord wSocketNo; /* [0.. DOCH_MAX_SOCKETS-1] */ + FLMutex mutex; /* Mutex for the socket*/ + FLBoolean bUseInterrupt; /* Wait on interrupt */ + FLBoolean bUseDMA; /* Use DMA for current data xfer */ + FLBoolean bUseBurst; /* Use Burst for current data xfer */ + FLWord wNumOfDevices; /* 2 if device #1 exists */ + FLNative nTotalCapacity; + FLWord wTotalNumOfPartitions; /* In both devices */ + DOCH_PartitionAttr partitionAttr[DOCH_MAX_PARTITIONS]; /* Partitions attributes */ + FLWord wLastPartitionSpanned; /* Last partition of device #0 spans to device #1 */ + DOCH device[ATA_MAX_NUM_OF_DEVICES]; /* ATA device #0, #1 */ + DOCH_HALRoutnies halRoutines; /* HAL routines structure*/ + DOCH_PartitionSpanData sSpanData; /*Span data as retrieved from Device User Attributes sector*/ +} DOCH_Socket; + +/* structure that holds addressing data (CHS/LBA) */ +typedef struct { + FLByte bSecNum; + FLByte bCylLow; + FLByte bCylHi; + FLByte bDevHead; +} Addressing_Values_s; + + +#ifdef __cplusplus +extern "C" { +#endif +extern DOCH_Socket sockets [DOCH_MAX_SOCKETS]; + +#define DOCH_get_socket(pdev, socketNo) \ + if(socketNo > (DOCH_MAX_SOCKETS-1)) \ + pdev = NULL; \ + else \ + pdev = &sockets[socketNo]; + + +/* API routines */ +extern DOCH* DOCH_get_disk(FLSNative socketNo, FLSNative devNum); +extern DOCH_Error doch_init_window (FLSNative socketNo, DOCH_InitSocket initSocket); +extern DOCH_Error doch_init_floors (DOCH_Socket* pdev,FLByte bConfFloor,FLByte * bFloorsNum); +extern DOCH_Error doch_init_socket (FLSNative socketNo, DOCH_InitSocket); +extern DOCH_Error doch_get_flags (FLSNative socketNo, FLSNative devNum, FLDword* flags); +extern DOCH_Error doch_set_flags (FLSNative socketNo, FLSNative devNum, FLDword flags); +extern DOCH_Error doch_command (FLSNative socketNo, FLSNative devNum, DOCH_Registers* in_regs, DOCH_Registers* out_regs, void* buf, FLNative secNum); +extern DOCH_Error doch_reset (DOCH_Socket* pdev); +extern DOCH_Error doch_setTransferMode (FLSNative socketNo, FLSNative devNum, DOCH_TransferMode tm, FLDword drqSize); +extern DOCH_TransferMode doch_getTransferMode (FLSNative socketNo, FLSNative devNum); +extern DOCH_Error doch_setConfigReg16(DOCH_Socket* pdev, FLDword registerOffset, FLNative registerValue); +extern FLWord doch_getConfigReg16(DOCH_Socket* pdev, FLSNative registerOffset); +extern DOCH_Error doch_configCommon(DOCH_Socket* pdev); +extern DOCH_Error clearATAInterrupt(FLSNative socketNo); + + +extern DOCH_Error doch_ata_passthru ( FLSNative socketNo, + FLSNative devNum, + DOCH_PassThru_Op ptOP, + DOCH_Registers * in_regs, + DOCH_Registers * out_regs, + void * buf, + FLNative secNum + ); + +extern DOCH_Error update_device_info(DOCH_Socket* pdev, + DOCH_DeviceInfo* diskOnChipDeviceInfo, + int devNum); + +DOCH_Error dochCheckPFSymptom(FLSNative socketNo, FLByte devNum, FLBoolean beforOrAfterCommand /* Used for debug prints */); + +DOCH_Error def_dochDelayUsec(FLDword usec,FLDword dwAccessTime); + +#define WAIT_FOR_UPLOAD_MAX_CYCLES 100 +#define DOCH_MINIMAL_PAGE_SIZE 0x4 /*2KB in sectors*/ +#define DOCH_MINIMAL_UNIT_SIZE 0x800 /*1MB in sectors*/ +#ifdef __cplusplus +} +#endif + +#endif /* DOCH_ATA_H */ diff -urN linux-2.6.30.4-orig/drivers/block/tffs/doch-firmware/doch-firmware.c linux-2.6.30.4/drivers/block/tffs/doch-firmware/doch-firmware.c --- linux-2.6.30.4-orig/drivers/block/tffs/doch-firmware/doch-firmware.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/doch-firmware/doch-firmware.c 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,206 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2006, msystems Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of msystems nor the names of its contributors may be */ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/******************************************************************************/ + +/*********************************************************************************** + * * + * This utility program updates firmware in mDOC H3 devices. It takes two * + * parameters: name of mDOC's device file (for example /dev/tffsa), and name * + * of mDOC firmware file (for example, "image.enc-0050"). Here is an example: * + * * + * doch-firmware /dev/tffsa image.enc-0050 * + * * + ***********************************************************************************/ + + +/* + * $Log$ + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include "tffsioct.h" + + + + +#ifndef FL_SECTOR_SIZE +# define FL_SECTOR_SIZE 512 +#endif + + + +/* + * Calculate simple checksum on buffer 'buf' containing 'buf_size' bytes. + * We expect 'buf_size' to be multiple of 4. + */ +static +unsigned long chksum (unsigned long * buf, int buf_size) +{ + register unsigned long s = 0; + register int n; + + assert ((buf != NULL) && ((buf_size % sizeof(long)) == 0)); + + for (n = ((buf_size / sizeof(long)) - 1); n >= 0; n--) + s ^= buf[n]; + + return s; +} + + + + +/* + * Write firmware to DiskOnChip via IOCTL call to DiskOnChip driver. + * We expect 'buf_size' to be multiple of sector size. + */ +static +int write_firmware (int fd, void * buf, int buf_size) +{ + flIOctlRecord ioctl_record; + flInputLnxRecord in; + flOutputLnxRecord out; + flAtaPassthrough ata_passthrough; + int rc; + + assert (buf != NULL); + assert ((buf_size % FL_SECTOR_SIZE) == 0); /* must be multiple of sector size */ + assert ((buf_size / FL_SECTOR_SIZE) <= 256); /* max 256 sectors at once */ + + ioctl_record.inputRecord = ∈ + ioctl_record.outputRecord = &out; + + in.command = 5; /* ATA pass through command */ + in.data = (unsigned long) &ata_passthrough; + + out.data = (unsigned long) NULL; + + memset (&ata_passthrough, 0, sizeof(ata_passthrough)); + ata_passthrough.socketNum = 0; + ata_passthrough.userBuff = buf; + ata_passthrough.userBuffSize = buf_size; + ata_passthrough.secNum = (buf_size / FL_SECTOR_SIZE); + ata_passthrough.passThruOP = DOCH_PASSTHRU_DATA_OUT; + ata_passthrough.in_regs.bCommandStatus = DOCH_DOWNLOAD_MICROCODE; + ata_passthrough.in_regs.bFeaturesError = DOCH_DLMCODE_DOWNLOAD_AND_SAVE; + ata_passthrough.in_regs.bSectorCount = (unsigned char) (buf_size / FL_SECTOR_SIZE); + ata_passthrough.in_regs.bSectorNumber = (unsigned char)((buf_size / FL_SECTOR_SIZE) >> 8); + + rc = ioctl (fd, FL_IOCTL_LNX, &ioctl_record); + if ((rc != 0) || (ata_passthrough.status != 0)) + { + fprintf (stderr, "Error %d writing DiskOnChip firmware\n", (int)out.status); + rc = -1; + } + else + fprintf (stdout, "Success writing DiskOnChip firmware\n"); + + return rc; +} + + + + +/* + * Main + */ +int main ( int argc, char * argv[] ) +{ + int fd; + void * buf; + int buf_size; + int rc = -1; + + /* arg check */ + if ((argc != 3) || (argv[1] == NULL) || (strlen(argv[1]) == 0) || + (argv[2] == NULL) || (strlen(argv[2]) == 0)) + { + fprintf (stderr, "Usage: doch-firmware \n"); + fprintf (stderr, "Example: doch-firmware /dev/tffsa image.enc-0050\n"); + exit (-1); + } + + /* open firmware file */ + if((fd = open(argv[2], O_RDONLY)) == -1) + { perror ("Can't open firmware file"); exit (-1); } + + /* find out size of firmware file */ + if ((buf_size = lseek(fd, 0, SEEK_END)) == -1) + { perror ("Can't determine size of firmware file"); exit (-1); } + + /* set file pointer back to start of firmware file */ + if( lseek(fd, 0, SEEK_SET) != 0) + { perror ("Can't rewind firmware file"); exit (-1); } + + /* allocate buffer to hold firmware file's contents, and clear it */ + if ((buf = calloc(buf_size + FL_SECTOR_SIZE, sizeof(char))) == NULL) + { perror ("Can't allocate memory"); exit (-1); } + + /* read firmware file into the buffer */ + if( read(fd, buf, buf_size) != buf_size ) + { perror ("Can't read firmware file"); exit (-1); } + + /* close firmware file */ + close (fd); + + /* round up 'buf_size' to multiple of FL_SECTOR_SIZE */ + buf_size = (((buf_size - 1) / FL_SECTOR_SIZE) + 1) * FL_SECTOR_SIZE; + + if ((buf_size / FL_SECTOR_SIZE) > 256) + { perror ("Firmware file too large"); free (buf); exit (-1); } + + /* calculate checksum on the buffer */ + fprintf (stdout, "Firmware file checksum 0x%lx\n", chksum(buf, buf_size)); + + /* open device file */ + if((fd = open(argv[1], O_RDWR)) == -1) + { perror ("Can't open device"); free (buf); exit (-1); } + + /* issue IOCTL to device */ + rc = write_firmware (fd, buf, buf_size); + + /* close device file */ + close (fd); + + /* clear and free allocated buffer */ + memset (buf, 0, buf_size); + free (buf); + + fprintf (stdout, "Reset DiskOnChip to activate new firmware\n"); + + exit (rc); +} diff -urN linux-2.6.30.4-orig/drivers/block/tffs/doch-firmware/Makefile linux-2.6.30.4/drivers/block/tffs/doch-firmware/Makefile --- linux-2.6.30.4-orig/drivers/block/tffs/doch-firmware/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/doch-firmware/Makefile 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,72 @@ +#================================================================================ +# +# Makefile for 'doch-firmware' (mDOC firmware upgrade) application. +# +#================================================================================ +# +# Copyright (C) 2006 msystems Ltd. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of msystems nor the names of its contributors may be +# used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +#=============================================================================== + + +# +# Specify path to usr/include as appropriate +# for your installation. +# +INCLUDE_DIR = /opt/ti/omap2420/rootfs-mvlcee31/usr/include + +# +# Specify compiler as appropriate for your installation. +# Default is ARM/GCC compiler. +# +CC = arm-unknown-linux-gnu-gcc + +# +# Specify compiler flags. +# +CFLAGS += -I$(INCLUDE_DIR) +CFLAGS += -I.. +CFLAGS += -Wall +# CFLAGS += -g + +# +# 'make all' rule +# +all : doch-firmware + +# +# make 'ioctl-example' demo application +# +doch-firmware : doch-firmware.c + $(CC) $(CFLAGS) -o $@ $< + +# +# 'make clean' rule +# +clean : + rm -f *.o doch-firmware + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/doch_func.h linux-2.6.30.4/drivers/block/tffs/doch_func.h --- linux-2.6.30.4-orig/drivers/block/tffs/doch_func.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/doch_func.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,171 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Test for 7.x/src/H3/doch_func.h-arc $ + * + * Rev 1.24 Dec 04 2007 17:33:22 einat.avidan + * Remove flDOCHWipeSectorsByWriting + * + * Rev 1.23 Oct 30 2007 17:02:56 einat.avidan + * add new function DOCHWipeSectorsByWriting + * + * Rev 1.22 Oct 22 2007 11:34:50 einat.avidan + * update copyrights header + * + * Rev 1.21 Oct 11 2007 18:48:58 Einat.Avidan + * Replace global Boolean pattern with pattern in size of + * byte instead of dWord + * + * Rev 1.20 Mar 13 2007 13:47:20 einat.avidan + * add support for SLPP + * + * Rev 1.19 Sep 11 2006 13:45:16 yaniv.iarovici + * Legal header added + * + * Rev 1.18 Aug 09 2006 17:26:54 Polina.Marimont + * initial for DOC Driver 1.0 + * + */ + +#ifndef DOCH_FUNC_H +#define DOCH_FUNC_H + +#include "flcommon.h" +#include "doch_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*Get Info*/ +DOCH_Error DOCHIdentifyDiskOnChipDevice(IOreq* ioreq); +DOCH_Error DOCHGetResetStatus(IOreq* ioreq); +DOCH_Error DOCHNotifyReset(IOreq* ioreq); +DOCH_Error DOCHNotifyPlatformResumed(IOreq* ioreq); +DOCH_Error DOCHPartitionInfo(IOreq* ioreq); +DOCH_Error DOCHSetDiskUserAttributes(IOreq* ioreq); +DOCH_Error DOCHGetDiskUserAttributes(IOreq* ioreq); +DOCH_Error DOCHGetConfigurationData(IOreq* ioreq); +DOCH_Error DOCHSetConfigurationData(IOreq* ioreq); + +/*Media*/ +DOCH_Error DOCHSetDefaultPartition(IOreq* ioreq); +DOCH_Error DOCHSetDataTransferMode(IOreq* ioreq); +DOCH_Error DOCHOptimizeMedia(IOreq* ioreq); +DOCH_Error DOCHDeletePartitions(IOreq* ioreq); +DOCH_Error DOCHAddPartition(IOreq* ioreq); +DOCH_Error DOCHUnformatDevice(IOreq* ioreq); +DOCH_Error DOCHWriteIPL(IOreq* ioreq); +DOCH_Error DOCHReadIPL(IOreq* ioreq); + +/*IO*/ +DOCH_Error DOCHReadPartitionSectors(IOreq* ioreq); +DOCH_Error DOCHWritePartitionSectors(IOreq* ioreq); +DOCH_Error DOCHWriteAndLock(IOreq* ioreq); +DOCH_Error DOCHWipeSectors(IOreq* ioreq); +DOCH_Error DOCHFreeSectors(IOreq* ioreq); +DOCH_Error DOCHPrepareForWrite(IOreq* ioreq); + + +/*Flexi-Flash*/ +DOCH_Error DOCHWriteFlexiFast(IOreq* ioreq); +DOCH_Error DOCHWriteFlexiNormal(IOreq* ioreq); +DOCH_Error DOCHReWriteFlexiNormal(IOreq* ioreq); + +/*Protection*/ +DOCH_Error DOCHAccessPartWithPwd(IOreq* ioreq); +DOCH_Error DOCHDisablePartAccess(IOreq* ioreq); +DOCH_Error DOCHSetParitionProtection(IOreq* ioreq); + +/*PKI*/ +DOCH_Error DOCHSendHostPublicKey(IOreq* ioreq); +DOCH_Error DOCHReceiveDochPublicKey(IOreq* ioreq); +DOCH_Error DOCHVerifyHostKey(IOreq* ioreq); + +/*Custom Parameters*/ +DOCH_Error DOCHGetCustomParameter(IOreq* ioreq); +DOCH_Error DOCHSetCustomParameter(IOreq* ioreq); + +/*Atomic Read/Write Sequence*/ +DOCH_Error DOCHManageAtomicWriteSeq(IOreq* ioreq); + +/*Algorithms*/ +DOCH_Error DOCHReportSupportedAlgorithms(IOreq* ioreq); +DOCH_Error DOCHGetAlgorithmCapabilities(IOreq* ioreq); +DOCH_Error DOCHSetAlgorithmMode(IOreq* ioreq); + +/*Hash*/ +DOCH_Error DOCHAutoHashControl(IOreq* ioreq); +DOCH_Error DOCHReadCalculatedHash(IOreq* ioreq); +DOCH_Error DOCHWriteCalculatedHash(IOreq* ioreq); +DOCH_Error DOCHReadOriginalHash(IOreq* ioreq); +DOCH_Error DOCHWriteGivenHash(IOreq* ioreq); +DOCH_Error DOCHStartHashStreamCalculation(IOreq* ioreq); +DOCH_Error DOCHReadStopHashStreamCalc(IOreq* ioreq); +DOCH_Error DOCHReturnRandomNumbers(IOreq* ioreq); +DOCH_Error DOCHSetHashKey(IOreq* ioreq); + +/*General*/ +DOCH_Error DOCHSetParitionUserAttributes(IOreq* ioreq); +DOCH_Error DOCHGetParitionUserAttributes(IOreq* ioreq); +DOCH_Error DOCHSetPowerMode(IOreq* ioreq); +DOCH_Error DOCHGetPowerMode(IOreq* ioreq); +DOCH_Error DOCHConfigHW(IOreq* ioreq); +DOCH_Error DOCHRecoverFromPowerLoss(IOreq* ioreq); +DOCH_Error DOCHClearIRQ(IOreq* ioreq); +DOCH_Error DOCHGetPhysicalAddress(IOreq* ioreq); + +#ifdef FL_SLPP +/*SLPP Specific*/ +DOCH_Error DOCHSLPPUnlockRange(IOreq* ioreq); +DOCH_Error DOCHSLPPUnlockEntirePartition(IOreq* ioreq); +DOCH_Error DOCHSLPPLockRange(IOreq* ioreq); +DOCH_Error DOCHSLPPStickyLockRange(IOreq* ioreq); +DOCH_Error DOCHSLPPReportLockedRanges(IOreq* ioreq); +#endif /*FL_SLPP*/ +#ifdef __cplusplus +} +#endif + +#endif /*DOCH_FUNC_H*/ + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/dochstub.c linux-2.6.30.4/drivers/block/tffs/dochstub.c --- linux-2.6.30.4-orig/drivers/block/tffs/dochstub.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/dochstub.c 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,121 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ + +/*This file holds necessary routines for integrating sureFS over DOCH SDK*/ + +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/version 7.0/TrueFFS FS/src/h3/dochstub.c-arc $ + * + * Rev 1.12 Oct 22 2007 11:34:50 einat.avidan + * update copyrights header + * + * Rev 1.11 Sep 11 2006 13:45:16 yaniv.iarovici + * Legal header added + * + * Rev 1.10 Aug 09 2006 17:26:54 Polina.Marimont + * initial for DOC Driver 1.0 + * + * Rev 1.9.1.0 Aug 08 2006 15:55:26 Polina.Marimont + * DOC Driver 1.0 initial + */ + +#include "flbase.h" +#include "flstruct.h" +#ifdef FL_MIGRATION_VERSION +#include "bddefs.h" +#else /*FL_MIGRATION_VERSION*/ +#include "fsdefs.h" +#endif /*FL_MIGRATION_VERSION*/ +#include "dochtl.h" +#include "doch_sys.h" +#include "doch_api.h" + + +FLMutex busy[DOCH_MAX_SOCKETS]; +FLBoolean dochStubInitialized = 0; +/*===========================*/ + +FLStatus dochSetBusy(FLByte socket, FLBoolean state, FLByte partition) +{ + FLStatus status = flOK; + + if (state == FL_ON) /* Set busy to ON */ + { + if (!flTakeMutex(&busy[socket])) + { + DBG_PRINT_FLOW_PRM(FLZONE_ATA, (FLTXT("\r\ndochSetMutex Failed to set mutex\r\n"))); + return flDriveNotAvailable; + } + } + else /* Set busy to OFF */ + { + flFreeMutex(&busy[socket]); + } + + return status; +} + +void setTL(FLByte socket, FLByte partition, TL * tl) +{ + FLNative i; + if (dochStubInitialized != TRUE) + { + dochStubInitialized = TRUE; + for (i = 0; i < DOCH_MAX_SOCKETS ; i ++) + flCreateMutex(&busy[i]); + } + getDochTL(tl, partition); +} + +#ifndef FL_MIGRATION_VERSION + +/* ----------------------------------------------------------------------------------- */ +FLStatus lockForIO(FLByte socket, FLByte partition, FLBoolean onOff) { + +checkStatus(dochSetBusy(socket, onOff, partition)); /* take BD mutex */ + +return flOK; +} +#endif /*FL_MIGRATION_VERSION*/ +/* ----------------------------------------------------------------------------------- */ + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/dochstub.h linux-2.6.30.4/drivers/block/tffs/dochstub.h --- linux-2.6.30.4-orig/drivers/block/tffs/dochstub.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/dochstub.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,72 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/version 7.0/TrueFFS FS/src/h3/dochstub.h-arc $ + * + * Rev 1.9 Oct 22 2007 11:34:50 einat.avidan + * update copyrights header + * + * Rev 1.8 Sep 11 2006 13:45:16 yaniv.iarovici + * Legal header added + * + * Rev 1.7 Aug 09 2006 17:26:54 Polina.Marimont + * initial for DOC Driver 1.0 + * + * Rev 1.6.1.0 Aug 08 2006 15:55:28 Polina.Marimont + * DOC Driver 1.0 initial + */ + +#ifndef DOCHSTUB +#define DOCHSTUB + +#ifndef FL_MIGRATION_VERSION +void setTL(FLByte socket, FLByte partition, TL * tl) ; +#else /*FL_MIGRATION_VERSION */ +void DOCH_setTL(FLByte socket, FLByte partition, TL* tl); +FLStatus dochSetBusy(FLByte socket, FLBoolean state, FLByte partition); +#endif /*FL_MIGRATION_VERSION*/ + +FLStatus DOCH_lockForIO(FLByte socket, FLByte partition, FLBoolean onOff); + +#endif /*DOCHSTUB*/ + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/doch_sys.h linux-2.6.30.4/drivers/block/tffs/doch_sys.h --- linux-2.6.30.4-orig/drivers/block/tffs/doch_sys.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/doch_sys.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,120 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/***********************************************************************************/ +/* */ +/* Header file for doch_sys module */ +/* */ +/***********************************************************************************/ + +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Test for 7.x/src/H3/doch_sys.h-arc $ + * + * Rev 1.17 Oct 22 2007 11:34:50 einat.avidan + * update copyrights header + * + * Rev 1.16 Feb 28 2007 09:58:42 einat.avidan + * No change + * + * Rev 1.15.1.0 Oct 31 2006 12:23:42 yaniv.iarovici + * Fix compilation warnings. + * + * Rev 1.15 Sep 11 2006 13:45:16 yaniv.iarovici + * Legal header added + * + * Rev 1.14 Aug 09 2006 17:26:54 Polina.Marimont + * initial for DOC Driver 1.0 + * + * Rev 1.13.1.0 Aug 08 2006 15:55:26 Polina.Marimont + * DOC Driver 1.0 initial + * + * Rev 1.13 May 18 2006 14:41:20 polina.marimont + * v1.40Fin1, PVCS log inside + */ + +#ifndef DOCH_SYS_H +#define DOCH_SYS_H + +#include "flcustom.h" + + +/* + * Access Layer API + */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + unsigned char (*hal_get_ata_reg) (volatile unsigned char *base, int reg); + void (*hal_set_ata_reg) (volatile unsigned char *base, int reg, unsigned int val); + unsigned short (*hal_get_ctrl_reg) (volatile unsigned char *base, int reg); + void (*hal_set_ctrl_reg) (volatile unsigned char *base, int reg, unsigned int val); + int (*hal_blk_read) (volatile unsigned char *base, unsigned char *buf, int sectors); + int (*hal_blk_write) (volatile unsigned char *base, unsigned char *buf, int sectors); + int (*hal_doch_release) (int socketNo); +} DOCH_HALRoutnies; + +#ifdef __cplusplus +} +#endif +#ifdef FL_MIGRATION_VERSION + +#ifndef DOCH_USE_FUNC +#include "defs.h" +#ifdef __cplusplus +extern "C" { +#endif +extern FLFlash * DOCHFlash; +#ifdef __cplusplus +} +#endif +#endif /* DOCH_USE_FUNC */ + +#endif /*FL_MIGRATION_VERSION*/ + +#endif /* DOCH_SYS_H */ + + + + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/dochtl.c linux-2.6.30.4/drivers/block/tffs/dochtl.c --- linux-2.6.30.4-orig/drivers/block/tffs/dochtl.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/dochtl.c 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,642 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Test for 7.x/src/H3/dochtl.c-arc $ + * + * Rev 1.30 Dec 25 2007 11:18:24 einat.avidan + * bug fix: multiple mount on the same partition caused memory leak. + * + * Rev 1.29 Dec 04 2007 17:35:20 einat.avidan + * bug fix: gDeviceTurnedOff defined as byte and not as boolean + * + * Rev 1.28 Oct 22 2007 11:34:50 einat.avidan + * update copyrights header + * + * Rev 1.27 Oct 11 2007 18:53:30 Einat.Avidan + * Replace global Boolean pattern with pattern in size of + * byte instead of dWord + * + * Rev 1.26 Jun 20 2007 12:04:52 einat.avidan + * Enable burst without DMA when dochTl is used + * + * Rev 1.25 Jan 07 2007 17:53:56 Einat.Avidan + * adjustment for a change in mDoc H3: + * flGetPartitionInfo now returns flOK when partition is both read and write protected. therefore need to check protection attributes of the partition during absMount. + * + * Rev 1.23.1.0 Oct 22 2006 14:53:42 yaniv.iarovici + * Fixed compilation warnings. + * + * Rev 1.23 Sep 11 2006 13:45:16 yaniv.iarovici + * Legal header added + * + * Rev 1.22 Sep 10 2006 10:03:42 Yaniv.Iarovici + * Fix compilation warning: Initialize tlRecTable[] and tlTable[] upon first entry to dochMountTL(). + * + * Rev 1.21 Aug 24 2006 11:39:46 Yaniv.Iarovici + * Change error returned by dochMountTL() in case DOCHPartitionInfo() failed to: + * - flHWProtection if the operation failed due to protection error + * - flGeneralFailure otherwise + * + * Rev 1.20 Aug 17 2006 15:20:36 Yaniv.Iarovici + * Zerioze partition info structure. + * + * Rev 1.18 Aug 09 2006 17:26:56 Polina.Marimont + * initial for DOC Driver 1.0 + * + */ + +#include "dochtl.h" +#include "doch_ata.h" +#include "doch_func.h" + +#ifdef FL_MIGRATION_VERSION +#include "tffs_api.h" +#endif /*FL_MIGRATION_VERSION*/ + +static DocTLRec tlRecTable[DOCH_MAX_PARTITIONS]; +static TL tlTable[DOCH_MAX_PARTITIONS]; + + +extern FLByte gIsDMAEnabled; /*DMA is Enabled/Disabled*/ + +#ifdef CHECK_POWER_ON_EVERY_COMMAND +extern FLByte gDeviceTurnedOff; +#endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#ifndef FL_MIGRATION_VERSION +bdCallType bdCall = bdCallSureFS; +#endif /*FL_MIGRATION_VERSION*/ + +static FLStatus dochMapSector(TLrec * tlRec, SectorNo sectorNo, void * *retBuffer) +{ + DOCH_Error rc; + IOreq ioreq; + DOCH_Socket* pdev; + DOCH_get_socket(pdev, tlRec->socketNo); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return flAdapterNotFound; + + tffsset(&ioreq, 0, sizeof(ioreq)); + + pdev->bAtaDevNum = 0; + DOCH_SET_SOCKET_TO_IOREQ_HANDLE(&ioreq, tlRec->socketNo); + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq, tlRec->partitionNo); + ioreq.irSectorNo = sectorNo; + ioreq.irSectorCount = 1; + ioreq.irData = tlRec->mappedSector; + + rc = flDOCHReadPartitionSectors(&ioreq); + + *retBuffer = tlRec->mappedSector; + + if(rc != DOCH_OK) + { + #ifdef CHECK_POWER_ON_EVERY_COMMAND + /*In case Power Fail was detected, return DOCH_DeviceTurnedOff*/ + if( gDeviceTurnedOff==DOCH_GLOBAL_BOOL_PATTERN ) + { + gDeviceTurnedOff = FALSE; + +#ifdef FL_MIGRATION_VERSION + return flSuspendModeDetected; +#else /*FL_MIGRATION_VERSION*/ + return DOCH_DeviceTurnedOff; +#endif /*FL_MIGRATION_VERSION*/ + } + #endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + + return flBadFunction; + } + else + return flOK; +} + +static FLStatus dochWriteSector(TLrec *tlRec, SectorNo sectorNo, void FAR1 *fromAddress) +{ + DOCH_Error rc; + IOreq ioreq; + DOCH_Socket* pdev; + DOCH_get_socket(pdev, tlRec->socketNo); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return flAdapterNotFound; + + tffsset(&ioreq, 0, sizeof(ioreq)); + + pdev->bAtaDevNum = 0; + DOCH_SET_SOCKET_TO_IOREQ_HANDLE(&ioreq, tlRec->socketNo); + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq, tlRec->partitionNo); + ioreq.irSectorNo = sectorNo; + ioreq.irSectorCount = 1; + ioreq.irData = fromAddress; + + rc = flDOCHWritePartitionSectors(&ioreq); + + if(rc != DOCH_OK) + { + #ifdef CHECK_POWER_ON_EVERY_COMMAND + /*In case Power Fail was detected, return DOCH_DeviceTurnedOff*/ + if( gDeviceTurnedOff==DOCH_GLOBAL_BOOL_PATTERN ) + { + gDeviceTurnedOff = FALSE; + +#ifdef FL_MIGRATION_VERSION + return flSuspendModeDetected; +#else /*FL_MIGRATION_VERSION*/ + return DOCH_DeviceTurnedOff; +#endif /*FL_MIGRATION_VERSION*/ + } + #endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + + if( (rc == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) || (rc == DOCH_ProtectionFault)) + return flHWProtection; + + return flBadFunction; + } + else + return flOK; +} + +static FLStatus dochWriteMultiSector(TLrec *tlRec, SectorNo sectorNo, void FAR1 *fromAddress,SectorNo sectorCount) +{ + DOCH_Error rc; + IOreq ioreq; + DOCH_Socket* pdev; + DOCH_get_socket(pdev, tlRec->socketNo); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return flAdapterNotFound; + + tffsset(&ioreq, 0, sizeof(ioreq)); + + pdev->bAtaDevNum = 0; + DOCH_SET_SOCKET_TO_IOREQ_HANDLE(&ioreq, tlRec->socketNo); + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq, tlRec->partitionNo); + ioreq.irSectorNo = sectorNo; + ioreq.irSectorCount = sectorCount; + ioreq.irData = fromAddress; + +#ifdef FL_MIGRATION_VERSION + #ifdef FL_USE_DMA_ON_WRITE +#endif /*FL_MIGRATION_VERSION*/ + +#ifdef DOCH_DMA_CONFIG + /*Check if to enable DMA*/ + if((((FLDword)fromAddress & 0x3) == 0) && (gIsDMAEnabled == DOCH_GLOBAL_BOOL_PATTERN)) + ioreq.irFlags |= DOCH_USE_DMA; +#endif /*DOCH_DMA_CONFIG*/ + +#ifdef FL_MIGRATION_VERSION + #endif /*FL_USE_DMA_ON_WRITE*/ +#endif /*FL_MIGRATION_VERSION*/ + +#ifdef DOCH_USE_BURST_MODE_WRITE + ioreq.irFlags |= DOCH_USE_BURST; +#endif /*DOCH_USE_BURST_MODE_WRITE*/ + + rc = flDOCHWritePartitionSectors(&ioreq); + + if(rc != DOCH_OK) + { + #ifdef CHECK_POWER_ON_EVERY_COMMAND + /*In case Power Fail was detected, return DOCH_DeviceTurnedOff*/ + if( gDeviceTurnedOff==DOCH_GLOBAL_BOOL_PATTERN ) + { + gDeviceTurnedOff = FALSE; + +#ifdef FL_MIGRATION_VERSION + return flSuspendModeDetected; +#else /*FL_MIGRATION_VERSION*/ + return DOCH_DeviceTurnedOff; +#endif /*FL_MIGRATION_VERSION*/ + } + #endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + + return flBadFunction; + } + else + return flOK; +} + +static FLStatus dochReadSectors(TLrec *tlRec, SectorNo sectorNo, void FAR1 *dest,SectorNo sectorCount) +{ + DOCH_Error rc; + IOreq ioreq; + DOCH_Socket* pdev; + DOCH_get_socket(pdev, tlRec->socketNo); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return flAdapterNotFound; + + tffsset(&ioreq, 0, sizeof(ioreq)); + + pdev->bAtaDevNum = 0; + DOCH_SET_SOCKET_TO_IOREQ_HANDLE(&ioreq, tlRec->socketNo); + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq, tlRec->partitionNo); + ioreq.irSectorNo = sectorNo; + ioreq.irSectorCount = sectorCount; + ioreq.irData = dest; + +#ifdef DOCH_DMA_CONFIG + /*Check if to enable DMA*/ + if((((FLDword)dest & 0x3) == 0) && (gIsDMAEnabled == DOCH_GLOBAL_BOOL_PATTERN)) + { + ioreq.irFlags |= DOCH_USE_DMA; + } +#endif /*DOCH_DMA_CONFIG*/ + +#ifdef FL_USE_BURST_MODE_READ + if( ((FLDword)ioreq.irData & 3) == 0 ) + { + ioreq.irFlags |= DOCH_USE_BURST; + } +#endif /* FL_USE_BURST_MODE_READ */ + + rc = flDOCHReadPartitionSectors(&ioreq); + if(rc != DOCH_OK) + { + #ifdef CHECK_POWER_ON_EVERY_COMMAND + /*In case Power Fail was detected, return DOCH_DeviceTurnedOff*/ + if( gDeviceTurnedOff==DOCH_GLOBAL_BOOL_PATTERN ) + { + gDeviceTurnedOff = FALSE; + +#ifdef FL_MIGRATION_VERSION + return flSuspendModeDetected; +#else /*FL_MIGRATION_VERSION*/ + return DOCH_DeviceTurnedOff; +#endif /*FL_MIGRATION_VERSION*/ + } + #endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + + return flBadFunction; + } + else + return flOK; +} + +static FLStatus dochDeleteSector(TLrec *tlRec, SectorNo sectorNo, SectorNo noOfSectors) +{ + DOCH_Error rc; + IOreq ioreq; + DOCH_Socket* pdev; + DOCH_get_socket(pdev, tlRec->socketNo); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return flAdapterNotFound; + + tffsset(&ioreq, 0, sizeof(ioreq)); + + pdev->bAtaDevNum = 0; + DOCH_SET_SOCKET_TO_IOREQ_HANDLE(&ioreq, tlRec->socketNo); + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq, tlRec->partitionNo); + ioreq.irSectorNo = sectorNo; + ioreq.irSectorCount = noOfSectors; + + rc = flDOCHFreeSectors(&ioreq); + + if(rc != DOCH_OK) + { + #ifdef CHECK_POWER_ON_EVERY_COMMAND + /*In case Power Fail was detected, return DOCH_DeviceTurnedOff*/ + if( gDeviceTurnedOff==DOCH_GLOBAL_BOOL_PATTERN ) + { + gDeviceTurnedOff = FALSE; + +#ifdef FL_MIGRATION_VERSION + return flSuspendModeDetected; +#else /*FL_MIGRATION_VERSION*/ + return DOCH_DeviceTurnedOff; +#endif /*FL_MIGRATION_VERSION*/ + } + #endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + + return flBadFunction; + } + else + return flOK; +} + +static FLStatus dochTlSetBusy(TLrec *tlRec, FLBoolean state) +{ + return flOK; +} + +static void dochDismount(TLrec *tlRec) +{ + FL_FREE(tlRec->mappedSector); +} + +static FLStatus dochDefragment(TLrec *tlRec, FLSDword FAR2 *sectorsNeeded, FLDword normalSpace) +{ + /*optimize*/ + return flOK; +} + +static FLStatus dochCheckVolume(TLrec *tlRec) +{ + return flOK; +} + +static SectorNo dochSectorsInVolume(TLrec *tlRec) +{ + SectorNo secNo = tlRec->virtualSectors; + + return secNo; +} + +static FLStatus dochGetTLInfo(TLrec *tlRec, TLInfo *tlInfo) +{ + return flOK; +} + +static void dochRecommendedClusterInfo(TLrec *tlRec, FLDword *sectorsPerCluster, FLDword *clusterAlignment) +{ + *sectorsPerCluster = tlRec->maxRelatedSectors; + *clusterAlignment = ((FLDword)tlRec->sectorsInUnit<socketNo); +#endif /*FL_MIGRATION_VERSION*/ + + tffscpy(tl, &tlTable[partition], sizeof(TL)); + + return flOK; +} + +FLStatus dochMountTL(FLNative partition, FLNative socket) +{ + static FLBoolean bStaticArraysInit = FALSE; + + IOreq ioreq; + DOCH_PartitionInfo partInfo; + DOCH_Error rc; + TL* tl; + DOCH_Socket* pdev; + FLByte protectionType,guestAccessMode,authenticated; + + /*Initialize static arrays*/ + if(!bStaticArraysInit) + { + tffsset(tlRecTable, 0, sizeof(tlRecTable)); + tffsset(tlTable, 0, sizeof(tlTable)); + bStaticArraysInit = TRUE; + } + + DOCH_get_socket(pdev, socket); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return flAdapterNotFound; + + /*Retrieve partition info*/ + tffsset(&partInfo, 0, sizeof(partInfo)); + tffsset(&ioreq, 0, sizeof(ioreq)); + DOCH_SET_SOCKET_TO_IOREQ_HANDLE(&ioreq, socket); + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq, partition); + pdev->bAtaDevNum = 0; + ioreq.irData = &partInfo; + rc = DOCHPartitionInfo(&ioreq); + if(rc != DOCH_OK) + { + #ifdef CHECK_POWER_ON_EVERY_COMMAND + /*In case Power Fail was detected, return DOCH_DeviceTurnedOff*/ + if( gDeviceTurnedOff==DOCH_GLOBAL_BOOL_PATTERN ) + { + gDeviceTurnedOff = FALSE; + +#ifdef FL_MIGRATION_VERSION + return flSuspendModeDetected; +#else /*FL_MIGRATION_VERSION*/ + return DOCH_DeviceTurnedOff; +#endif /*FL_MIGRATION_VERSION*/ + } + #endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + + if(rc == DOCH_ProtectionFault) + return flHWProtection; + + return flGeneralFailure; + } + protectionType = (FLByte)(partInfo.partitionAttributes2 & DOCH_PA2B_PROTECTION_TYPE); + guestAccessMode = (FLByte)((partInfo.partitionAttributes2 & DOCH_PA2B_GUEST_MODE) >> DOCH_PA2O_GUEST_MODE); + authenticated = (FLByte)((partInfo.dwCommandFlagsOrStatuses & DOCH_CFSB_USER_AUTHENTICATED) >> DOCH_CFSO_USER_AUTHENTICATED); + + if ((protectionType != DOCH_PARTITION_NOT_PROTECTED) && (guestAccessMode == DOCH_PART_ACCESS_MODE_NONE)) + { + /* partition is READ_PROTECTED and WRITE_PROTECTED*/ + if (!(authenticated && protectionType != DOCH_PARTITION_NOT_PROTECTED)) + { + /*key is not inserted*/ + return flHWProtection; + } + + } + tl = &tlTable[partition]; + + /*Set tlRec*/ + /*=========*/ + tlRecTable[partition].partitionNo = partition; + tlRecTable[partition].socketNo = socket; + tlRecTable[partition].virtualSectors = partInfo.nPartitionSize; + tl->rec = &tlRecTable[partition]; + + /*Allocate 1 sector for mapping*/ + /*=============================*/ + /* allocate mappedSector only if not already allocated*/ + if (tl->rec->mappedSector==NULL) + tl->rec->mappedSector = FL_MALLOC(DOCH_SECTOR_SIZE); + + /*Fill TL parameters*/ + /*==================*/ + tl->cylinders = 0; + tl->heads = 0; + tl->sectorsPerTrack = 0; + tl->recommendedSectorsInCluster = partInfo.wRecommendedSectorsPerCluster; + tl->normalArea_SectorsInUnit_Bits = partInfo.wNormalAreaSectorsInErasableUnit; + tl->riskZoneSectors = 8; + + /*Fill TL routines*/ + /*================*/ + tl->mapSector = dochMapSector; + tl->writeSector = dochWriteSector; + tl->writeMultiSector = dochWriteMultiSector; + tl->readSectors = dochReadSectors; + tl->deleteSector = dochDeleteSector; + tl->tlSetBusy = dochTlSetBusy; + tl->dismount = dochDismount; + tl->defragment = dochDefragment; + tl->checkVolume = dochCheckVolume; + tl->sectorsInVolume = dochSectorsInVolume; + tl->getTLInfo = dochGetTLInfo; + tl->recommendedClusterInfo = dochRecommendedClusterInfo; + tl->readBBT = dochReadBBT; + tl->notifyChange = dochNotifyChange; + tl->completeOperation = dochCompleteOperation; + tl->getLastMappedSectorAddress = dochGetLastMappedSectorAddress; + tl->ensureFreeSectorsInUnit = dochEnsureFreeSectorsInUnit; + + return flOK; +} + + +#ifndef FL_MIGRATION_VERSION +TFFS_DLL_API FLStatus bdCallSureFS(FLFunctionNo functionNo, IOreq FAR2 *ioreq) +{ + switch(functionNo) + { + case FL_ABS_MOUNT: + return dochMountTL(FL_GET_FLASH_PARTITION_FROM_HANDLE(ioreq), FL_GET_SOCKET_FROM_HANDLE(ioreq)); + + case FL_DISMOUNT_VOLUME: + return flOK; + + default: + return flFeatureNotSupported; + } + +} + +TFFS_DLL_API FLStatus NAMING_CONVENTION flInit(void) +{ + DOCH_Error rc; + + rc = DochSDKInit(); + if(rc != DOCH_OK) + { + #ifdef CHECK_POWER_ON_EVERY_COMMAND + /*In case Power Fail was detected, return DOCH_DeviceTurnedOff*/ + if( gDeviceTurnedOff==DOCH_GLOBAL_BOOL_PATTERN ) + { + gDeviceTurnedOff = FALSE; + +#ifdef FL_MIGRATION_VERSION + return flSuspendModeDetected; +#else /*FL_MIGRATION_VERSION*/ + return DOCH_DeviceTurnedOff; +#endif /*FL_MIGRATION_VERSION*/ + } + #endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + + return flBadFunction; + } + + return flOK; +} + +TFFS_DLL_API void NAMING_CONVENTION flExit(void) +{ + doch_release_socket(0); +} + +#else /* FL_MIGRATION_VERSION not defined */ + +/******************************************/ +/* Function name : dochDismountTL */ +/* Description : */ +/* Return type : FLStatus */ +/* Argument : FLNative partition */ +/******************************************/ +FLStatus dochDismountTL(FLNative partition) +{ + TL* tl; + + tl = &tlTable[partition]; + + if( tl->rec->mappedSector != NULL ) + { + FL_FREE(tl->rec->mappedSector); + tl->rec->mappedSector = NULL; + } + + return flOK; +}/* dochDismountTL() */ + +#endif /*FL_MIGRATION_VERSION*/ + + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/dochtl.h linux-2.6.30.4/drivers/block/tffs/dochtl.h --- linux-2.6.30.4-orig/drivers/block/tffs/dochtl.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/dochtl.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,84 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Test for 7.x/src/H3/dochtl.h-arc $ + * + * Rev 1.15 Oct 22 2007 11:34:50 einat.avidan + * update copyrights header + * + * Rev 1.14 Sep 11 2006 13:45:16 yaniv.iarovici + * Legal header added + * + * Rev 1.13 Aug 09 2006 17:26:56 Polina.Marimont + * initial for DOC Driver 1.0 + * + */ + +#ifndef DOCHTL_H +#define DOCHTL_H + +#include "fltl.h" + + +struct tTLrec{ + FLByte socketNo; /* Socket number of the volume */ + FLByte partitionNo; /* Partition number of the volume */ + FLDword virtualSectors; /* No of sectors exported by the TL */ + FLByte maxRelatedSectors; /* Max number of sectors that might be written together */ + FLWord sectorsInUnit; /* No of sectors in a logical unit */ + + void FAR0 * mappedSector; +}; + +typedef TLrec DocTLRec; + +FLStatus getDochTL(TL* tl, FLByte partition); +FLStatus dochMountTL(FLNative partition, FLNative socket); + +#ifndef FL_MIGRATION_VERSION +TFFS_DLL_API FLStatus bdCallSureFS(FLFunctionNo functionNo, IOreq FAR2 *ioreq); +#else /*FL_MIGRATION_VERSION*/ +FLStatus dochDismountTL(FLNative partition); +#endif /*FL_MIGRATION_VERSION*/ +#endif /*DOCHTL_H*/ + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/docsys.c linux-2.6.30.4/drivers/block/tffs/docsys.c --- linux-2.6.30.4-orig/drivers/block/tffs/docsys.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/docsys.c 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,1304 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/3/bddoc/src/docsys.c-arc $ + * + * Rev 1.9 Oct 22 2007 11:34:50 einat.avidan + * update copyrights header + * + * Rev 1.8 Mar 11 2007 16:37:30 einat.avidan + * bug fix: working on x86 requires read buffer not to be paged out + * replace the former solution (access to the begining and the end of the buffer) + * with full solution: usage of a buffer that is locked on RAM + * + * Rev 1.7 Feb 28 2007 09:53:44 einat.avidan + * No change + * + * Rev 1.6.1.0 Nov 13 2006 15:13:50 Yaniv.Iarovici + * Added environment variable - 'FL_DISABLE_MEMCPY'. + * + * Rev 1.6 Oct 05 2006 11:00:48 yaniv.iarovici + * Removed support for flUse8Bit. + * + * Rev 1.5 Sep 11 2006 13:45:18 yaniv.iarovici + * Legal header added + * + * Rev 1.4 Aug 09 2006 16:52:44 Polina.Marimont + * initial for DOC Driver 1.0 + */ + +#include "docsys.h" +#ifdef FL_PARALLEL_MTD_SUPPORT +#include "pacclayr.h" +#endif /* FL_PARALLEL_MTD_SUPPORT */ + +FLBoolean flPreventMemcpy = 0; + +#ifndef FL_NO_USE_FUNC + +/*********************************************************/ +/* Report DiskOnChip Memory size */ +/*********************************************************/ + +/*---------------------------------------------------------------------- + f l D o c M e m W i n S i z e N o S h i f t + + This routine is called from MTD to quary the size of the DiskOnChip + memory window for none shifted DiskOnChip. +------------------------------------------------------------------------*/ + +FLDword FAR1 flDocMemWinSizeNoShift(void) +{ + return 0x2000; +} + +/*---------------------------------------------------------------------- + f l D o c M e m W i n S i z e S i n g l e S h i f t + + This routine is called from MTD to quary the size of the DiskOnChip + memory window for DiskOnChip connected with a single addres shift. +------------------------------------------------------------------------*/ + +FLDword FAR1 flDocMemWinSizeSingleShift(void) +{ + return 0x4000; +} + +/*---------------------------------------------------------------------- + f l D o c M e m W i n S i z e D o u b l e S h i f t + + This routine is called from MTD to quary the size of the DiskOnChip + memory window for DiskOnChip connected with a double addres shift. +------------------------------------------------------------------------*/ + +FLDword FAR1 flDocMemWinSizeDoubleShift(void) +{ + return 0x8000; +} + +/*********************************************************/ +/* Write 16 bits to DiskOnChip memory window */ +/*********************************************************/ + + +/*---------------------------------------------------------------------- + f l W r i t e 16 b i t U s i n g 8 b i t s N o S h i f t + + Write 16-bits Using 8-bits operands and 8 bit data + With no address shifted. +------------------------------------------------------------------------*/ + +void FAR1 flWrite16bitUsing8bitsNoShift(volatile FLByte FAR0 * win, FLWord offset,FLWord val) +{ +#ifndef FL_BIG_ENDIAN + FLWRITE_IO_BYTE((FLByte)val,(win + offset)); + FLWRITE_IO_BYTE((FLByte)(val>>0x8),(win + offset+1)); +#else + FLWRITE_IO_BYTE((FLByte)(val>>0x8),(win + offset)); + FLWRITE_IO_BYTE((FLByte)val,(win + offset + 1)); +#endif /* FL_BIG_ENDIAN */ +} + +/*---------------------------------------------------------------------- + f l W r i t e 1 6 b i t U s i n g 1 6 b i t s N o S h i f t + + Note : offset must be 16-bits aligned. + + Note2 : Used for if_cfg = 16 when using address shift. + + Write 16-bit Using 16-bits operands and 16-bits of data + with no address shifted. +------------------------------------------------------------------------*/ + +void FAR1 flWrite16bitUsing16bitsNoShift(volatile FLByte FAR0 * win, FLWord offset,Reg16bitType val) +{ + FLWRITE_IO_WORD(val,((volatile FLWord FAR0 *)win + (offset>>1))); +} + +/*---------------------------------------------------------------------- + f l W r i t e 1 6 b i t U s i n g 3 2 b i t s S i n g l e S h i f t + + Note : offset must be 16-bits aligned. + + Write 16-bit Using 32-bits operands and 16-bits of data + With a single address shifted. +------------------------------------------------------------------------*/ + +void FAR1 flWrite16bitUsing32bitsSingleShift(volatile FLByte FAR0 * win, FLWord offset,Reg16bitType val) +{ +#ifdef FL_BIG_ENDIAN + FLWRITE_IO_DWORD((FLDword)(((FLDword)val)<<16),(((volatile FLDword FAR0 *)win)+(offset>>1))); +#else + FLWRITE_IO_DWORD((FLDword)val,(((volatile FLDword FAR0 *)win)+(offset>>1))); +#endif /* FL_BIG_ENDIAN */ +} + +/*---------------------------------------------------------------------- + f l W r i t e 1 6 b i t U s i n g 1 6 b i t s S i n g l e S h i f t + + Note : offset must be 16-bits aligned. + + Note2 : Used for if_cfg = 8 when using address shift. + + Write 16-bit Using 16-bits operands and 8-bits of data + with a single address shifted. +------------------------------------------------------------------------*/ + +void FAR1 flWrite16bitUsing16bitsSingleShift(volatile FLByte FAR0 * win, FLWord offset,Reg16bitType val) +{ +#ifdef FL_BIG_ENDIAN + FLWRITE_IO_WORD((FLWord)(val>>8),(((volatile FLWord FAR0 *)win) + offset)); + FLWRITE_IO_WORD((FLWord)(val),(((volatile FLWord FAR0 *)win) + (offset+1))); +#else + FLWRITE_IO_WORD(val,(((volatile FLWord FAR0 *)win) + offset)); + FLWRITE_IO_WORD((FLWord)(val>>8),(((volatile FLWord FAR0 *)win) + (offset + 1))); +#endif /* FL_BIG_ENDIAN */ +} + +/*---------------------------------------------------------------------- + f l W r i t e 1 6 b i t U s i n g 3 2 b i t s D o u b l e S h i f t + + Note : offset must be 16-bits aligned. + + Note2 : Used for if_cfg = 8 when using address shift. + + Write 16-bit Using 32-bits operands and 8-bits of data + with a single address shifted. +------------------------------------------------------------------------*/ + +void FAR1 flWrite16bitUsing32bitsDoubleShift(volatile FLByte FAR0 * win, FLWord offset,Reg16bitType val) +{ +#ifdef FL_BIG_ENDIAN + FLWRITE_IO_DWORD(((FLDword)(val>>8)),(((volatile FLDword FAR0 *)win) + offset)); + FLWRITE_IO_DWORD(((FLDword)((FLByte)val)),(((volatile FLDword FAR0 *)win) + (offset + 1))); +#else + FLWRITE_IO_DWORD(((FLDword)((FLByte)val)),(((volatile FLDword FAR0 *)win) + offset)); + FLWRITE_IO_DWORD(((FLDword)(val>>8)),(((volatile FLDword FAR0 *)win) + (offset + 1))); +#endif /* FL_BIG_ENDIAN */ +} + +/*********************************************************/ +/* Read 16 bits from DiskOnChip memory window */ +/*********************************************************/ + + +/*---------------------------------------------------------------------- + f l R e a d 16 b i t U s i n g 8 b i t s N o S h i f t + + Read 16-bits Using 8-bits operands and 8-bits of data + With no address shifted. +------------------------------------------------------------------------*/ + +FLWord FAR1 flRead16bitUsing8bitsNoShift(volatile FLByte FAR0 * win,FLWord offset) +{ +#ifndef FL_BIG_ENDIAN + register FLWord val = (FLWord)FLREAD_IO_BYTE((win+offset)); + return val | (((FLWord)FLREAD_IO_BYTE((win+offset+1)))<<8); +#else + register FLWord val = ((FLWord)FLREAD_IO_BYTE(win+offset))<<8; + return val | ((FLWord)FLREAD_IO_BYTE(win+offset+1)); +#endif /* FL_BIG_ENDIAN */ +} + +/*---------------------------------------------------------------------- + f l R e a d 1 6 b i t U s i n g 1 6 b i t s N o S h i f t + + Note : offset must be 16-bits aligned. + + Read 16-bit Using 16-bits operands and 16-bits of data + With no address shifted. +------------------------------------------------------------------------*/ + +Reg16bitType FAR1 flRead16bitUsing16bitsNoShift(volatile FLByte FAR0 * win,FLWord offset) +{ + return( FLREAD_IO_WORD(((volatile FLWord FAR0 *)win + (offset>>1))) ); +} + +/*---------------------------------------------------------------------- + f l R e a d 1 6 b i t U s i n g 3 2 b i t s S i n g l e S h i f t + + Note : offset must be 16-bits aligned. + + Note2 : Used for if_cfg = 16 when using address shift. + + Read 16-bit Using 32-bits operands and 16-bits of data + With single address shifted. +------------------------------------------------------------------------*/ + +Reg16bitType FAR1 flRead16bitUsing32bitsSingleShift(volatile FLByte FAR0 * win,FLWord offset) +{ +#ifdef FL_BIG_ENDIAN + return (Reg16bitType) (FLREAD_IO_DWORD(((volatile FLDword FAR0*)win)+(offset>>1))>>16); +#else + return((Reg16bitType)FLREAD_IO_DWORD(((volatile FLDword FAR0 *)win)+(offset>>1))); +#endif /* FL_BIG_ENDIAN */ +} + +/*---------------------------------------------------------------------- + f l R e a d 1 6 b i t U s i n g 1 6 b i t s S i n g l e S h i f t + + Note : offset must be 16-bits aligned. + + Note2 : Used for if_cfg = 8 when using address shift. + + Read 16-bit Using 16-bits operands and 8-bits of data + With single address shifted. +------------------------------------------------------------------------*/ + +Reg16bitType FAR1 flRead16bitUsing16bitsSingleShift(volatile FLByte FAR0 * win,FLWord offset) +{ + FLByte val[2]; + + val[0] = ((Reg8bitType)(FLREAD_IO_WORD(((volatile FLWord FAR0 *)win)+offset))); + val[1] = ((Reg8bitType)(FLREAD_IO_WORD(((volatile FLWord FAR0 *)win)+(offset+1)))); + + return *((Reg16bitType *)val); +} + +/*---------------------------------------------------------------------- + f l R e a d 1 6 b i t U s i n g 3 2 b i t s D o u b l e S h i f t + + Note : offset must be 16-bits aligned. + + Note2 : Used for if_cfg = 8 when using address shift. + + Read 16-bit Using 32-bits operands and 8-bits of data + With double address shifted. +------------------------------------------------------------------------*/ + +Reg16bitType FAR1 flRead16bitUsing32bitsDoubleShift(volatile FLByte FAR0 * win,FLWord offset) +{ + FLByte val[2]; + + val[0] = ((Reg8bitType)(FLREAD_IO_DWORD(((volatile FLDword FAR0 *)win)+offset))); + val[1] = ((Reg8bitType)(FLREAD_IO_DWORD(((volatile FLDword FAR0 *)win)+(offset+1)))); + + return *((Reg16bitType *)val); +} + + +/*********************************************************/ +/* Write 8 bits to DiskOnChip memory window */ +/*********************************************************/ + +/*---------------------------------------------------------------------- + f l W r i t e 8 b i t U s i n g 8 b i t s N o S h i f t + + Write 8-bits Using 8-bits operands with no address shifted. +------------------------------------------------------------------------*/ + +void FAR1 flWrite8bitUsing8bitsNoShift(volatile FLByte FAR0 * win, FLWord offset,Reg8bitType val) +{ + FLWRITE_IO_BYTE(val,win + offset); +} + + +/*---------------------------------------------------------------------- + f l W r i t e 8 b i t U s i n g 16 b i t s N o S h i f t + + Note : DiskOnChip is connected with 16-bit data bus. + Note : Data is written only to lower memory addresses. + + Write 8-bits Using 16-bits operands with no address shifted. +------------------------------------------------------------------------*/ + +void FAR1 flWrite8bitUsing16bitsNoShift(volatile FLByte FAR0 * win, FLWord offset,Reg8bitType val) +{ +#ifdef FL_BIG_ENDIAN + FLWRITE_IO_WORD(((FLWord)val)<<8,((volatile FLWord FAR0 *)win)+(offset>>1)); +#else + FLWRITE_IO_WORD((FLWord)val,(((volatile FLWord FAR0 *)win)+(offset>>1))); +#endif /* FL_BIG_ENDIAN */ +} + +/*---------------------------------------------------------------------- + f l W r i t e 8 b i t U s i n g 16 b i t s S i n g l e S h i f t + + Note : Data is written only to 8-LSB. + + Write 8-bits Using 16-bits operands with Single address shifted. +------------------------------------------------------------------------*/ + +void FAR1 flWrite8bitUsing16bitsSingleShift(volatile FLByte FAR0 * win, FLWord offset,Reg8bitType val) +{ + FLWRITE_IO_WORD((FLWord)val,(((volatile FLWord FAR0 *)win)+offset)); +} + +/*---------------------------------------------------------------------- + f l W r i t e 8 b i t U s i n g 32 b i t s S i n g l e S h i f t + + Note : DiskOnChip is connected with 16-bit data bus. + Note : Data is written to both data bus 8-bits + + Write 8-bits Using 32-bits operands with single address shifted. +------------------------------------------------------------------------*/ + +void FAR1 flWrite8bitUsing32bitsSingleShift(volatile FLByte FAR0 * win, FLWord offset,Reg8bitType val) +{ +#ifdef FL_BIG_ENDIAN + FLWRITE_IO_DWORD(((FLDword)((FLDword)val*0x01010101L)),(((volatile FLDword FAR0 *)win)+(offset>>1))); +#else + FLWRITE_IO_DWORD((FLDword)val,(((volatile FLDword FAR0 *)win)+(offset>>1))); +#endif /* FL_BIG_ENDIAN */ +} + +/*---------------------------------------------------------------------- + f l W r i t e 8 b i t U s i n g 32 b i t s D o u b l e S h i f t + + Note : Data is written only to 8-LSB. + + Write 8-bits Using 32-bits operands with Double address shifted. +------------------------------------------------------------------------*/ + +void FAR1 flWrite8bitUsing32bitsDoubleShift(volatile FLByte FAR0 * win, FLWord offset,Reg8bitType val) +{ + FLWRITE_IO_DWORD((FLDword)val,(((volatile FLDword FAR0 *)win)+offset)); +} + +/*********************************************************/ +/* Read 8 bits to DiskOnChip memory window */ +/*********************************************************/ + +/*---------------------------------------------------------------------- + f l R e a d 8 b i t U s i n g 8 b i t s N o S h i f t + + Read 8-bits Using 8-bits operands with no address shifted. +------------------------------------------------------------------------*/ + +Reg8bitType FAR1 flRead8bitUsing8bitsNoShift(volatile FLByte FAR0 * win,FLWord offset) +{ + return FLREAD_IO_BYTE(((volatile void FAR0 *)(win + offset))); +} + + +/*---------------------------------------------------------------------- + f l R e a d 8 b i t U s i n g 16 b i t s N o S h i f t + + Note : DiskOnChip is connected with 16-bit data bus. + + Read 8-bits Using 16-bits operands with no address shifted. +------------------------------------------------------------------------*/ + +Reg8bitType FAR1 flRead8bitUsing16bitsNoShift(volatile FLByte FAR0 * win,FLWord offset) +{ +#ifdef FL_BIG_ENDIAN + return (((offset & 0x1) == 0) ? +#else + return (( offset & 0x1 ) ? +#endif /* FL_BIG_ENDIAN */ + (Reg8bitType)(FLREAD_IO_WORD(((volatile FLWord FAR0 *)win + (offset>>1))) >> 8) : + (Reg8bitType)(FLREAD_IO_WORD(((volatile FLWord FAR0 *)win + (offset>>1)))) ); + +} + +/*---------------------------------------------------------------------- + f l R e a d 8 b i t U s i n g 16 b i t s S i n g l e S h i f t + + Note : Assume data is found in 8-LSB of DiskOnChip + + Read 8-bits Using 16-bits operands with Single address shifted. +------------------------------------------------------------------------*/ + +Reg8bitType FAR1 flRead8bitUsing16bitsSingleShift(volatile FLByte FAR0 * win,FLWord offset) +{ + return( (Reg8bitType)FLREAD_IO_WORD((((volatile FLWord FAR0 *)win)+offset)) ); +} + +/*---------------------------------------------------------------------- + f l R e a d 8 b i t U s i n g 32 b i t s S i n g l e S h i f t + + Note : DiskOnChip is connected with 16-bit data bus. + + Read 8-bits Using 16-bits operands with Single address shifted. +------------------------------------------------------------------------*/ + +Reg8bitType FAR1 flRead8bitUsing32bitsSingleShift(volatile FLByte FAR0 * win,FLWord offset) +{ +#ifdef FL_BIG_ENDIAN + return (((offset & 0x1) == 0) ? + (Reg8bitType)(FLREAD_IO_DWORD(((volatile FLDword FAR0 *)win)+(offset>>1))>>24) : + (Reg8bitType)(FLREAD_IO_DWORD(((volatile FLDword FAR0 *)win)+(offset>>1))>>16)); +#else + return (( offset & 0x1 ) ? + (Reg8bitType)(FLREAD_IO_DWORD(((volatile FLDword FAR0 *)win)+(offset>>1))>>8) : + (Reg8bitType)(FLREAD_IO_DWORD(((volatile FLDword FAR0 *)win)+(offset>>1))) ); +#endif /* FL_BIG_ENDIAN */ +} + +/*---------------------------------------------------------------------- + f l R e a d 8 b i t U s i n g 32 b i t s D o u b l e S h i f t + + Note : Assume data is found in 8-LSB of DiskOnChip + + Read 8-bits Using 16-bits operands with Single address shifted. +------------------------------------------------------------------------*/ + +Reg8bitType FAR1 flRead8bitUsing32bitsDoubleShift(volatile FLByte FAR0 * win,FLWord offset) +{ + return((Reg8bitType)FLREAD_IO_DWORD(((volatile FLDword FAR0 *)win)+offset)); +} + +/*********************************************************/ +/*********************************************************/ +/*** Operation on several bytes (read/write/set) ***/ +/*********************************************************/ +/*********************************************************/ + +/*************************************************/ +/* 8-Bit DiskOnChip - No Shift */ +/*************************************************/ + +/*---------------------------------------------------------------------- + f l 8 b i t D o c R e a d N o S h i f t + + Read 'count' bytes, from a none shifted address bus using tffscpy. +------------------------------------------------------------------------*/ + +void FAR1 fl8bitDocReadNoShift(volatile FLByte FAR0 * win,FLWord offset,FLByte FAR1* dest,FLWord count) +{ +#ifdef FL_ENVIRONMENT_VARS + if(flPreventMemcpy == 1) + { + register int i ; + + for(i = 0 ; i < count ; i++) + dest[i] = FLREAD_IO_BYTE(win + offset + i); + } + else +#endif /* FL_ENVIRONMENT_VARS */ + TFFSCPY_FROM_IO_8_BITS(dest,win+offset,count); +} + +/*---------------------------------------------------------------------- + f l 8 b i t D o c W r i t e N o S h i f t + + Write 'count' bytes, from a none shifted address bus using tffscpy. +------------------------------------------------------------------------*/ + +void FAR1 fl8bitDocWriteNoShift(volatile FLByte FAR0 * win,FLWord offset,FLByte FAR1* src,FLWord count) +{ +#ifdef FL_ENVIRONMENT_VARS + if(flPreventMemcpy == 1) + { + register int i ; + + for(i = 0 ; i < count ; i++) + FLWRITE_IO_BYTE(src[i],win + offset + i); + } + else +#endif /* FL_ENVIRONMENT_VARS */ + TFFSCPY_TO_IO_8_BITS(win+offset,src,count); +} + +/*---------------------------------------------------------------------- + f l 8 b i t D o c S e t N o S h i f t + + Set 'count' bytes, from a none shifted address bus using tffsset. +------------------------------------------------------------------------*/ + +void FAR1 fl8bitDocSetNoShift(volatile FLByte FAR0 * win,FLWord offset,FLWord count, FLByte val) +{ +#ifdef FL_ENVIRONMENT_VARS + if(flPreventMemcpy == 1) + { + register int i ; + for(i = 0 ; i < count ; i++) + FLWRITE_IO_BYTE(val,win + offset + i); + } + else +#endif /* FL_ENVIRONMENT_VARS */ + TFFSSET_IO_8_BITS(win+offset,val,count); +} + +/*************************************************/ +/* 8-Bit DiskOnChip - Single Shift */ +/*************************************************/ + +/*---------------------------------------------------------------------- + f l 8 b i t D o c R e a d S i n g l e S h i f t + + Note : Assume data is found in 8-LSB of DiskOnChip + + Read 'count' bytes, from data bus's LSB lane with 1 address shifted +------------------------------------------------------------------------*/ + +void FAR1 fl8bitDocReadSingleShift(volatile FLByte FAR0 * win,FLWord offset,FLByte FAR1* dest,FLWord count) +{ + volatile FLWord FAR0 * doc = ((volatile FLWord FAR0 *)win) + offset; + register int i; + + + for(i=0;( i < count );i++) + dest[i] = (Reg8bitType)FLREAD_IO_WORD(doc+i); +} + +/*---------------------------------------------------------------------- + f l 8 b i t D o c W r i t e S i n g l e S h i f t + + Note : Assume data is found in 8-LSB of DiskOnChip + + Write 'count' bytes, to data bus's LSB lane with 1 address shifted. +------------------------------------------------------------------------*/ + +void FAR1 fl8bitDocWriteSingleShift(volatile FLByte FAR0 * win,FLWord offset,FLByte FAR1* src,FLWord count) +{ + volatile FLWord FAR0 * doc = ((volatile FLWord FAR0 *)win) + offset; + register int i; + + for(i=0;( i < count );i++) + FLWRITE_IO_WORD((FLWord)(src[i]),doc+i); +} + +/*---------------------------------------------------------------------- + f l 8 b i t D o c S e t S i n g l e S h i f t + + Note : Assume data is found in 8-LSB of DiskOnChip + + Set 'count' bytes, of data bus's LSB lane with 1 address shifted. +------------------------------------------------------------------------*/ + +void FAR1 fl8bitDocSetSingleShift(volatile FLByte FAR0 * win,FLWord offset,FLWord count, FLByte val) +{ + volatile FLWord FAR0 * doc = ((volatile FLWord FAR0 *)win) + offset; + register int i; + + for(i=0;( i < count );i++) + FLWRITE_IO_WORD((FLWord)val,doc+i); +} + +/*************************************************/ +/* 8-Bit DiskOnChip - Double Shift */ +/*************************************************/ + +/*---------------------------------------------------------------------- + f l 8 b i t D o c R e a d D o u b l e S h i f t + + Note : Assume data is found in 8-LSB of DiskOnChip + + Read 'count' bytes, from data bus's LSB lane with 2 address shifted. +------------------------------------------------------------------------*/ + +void FAR1 fl8bitDocReadDoubleShift(volatile FLByte FAR0 * win,FLWord offset,FLByte FAR1* dest,FLWord count) +{ + volatile FLDword FAR0 *doc = ((volatile FLDword FAR0 *)win) + offset; + register int i; + + + for(i=0;( i < count );i++) + dest[i] = (Reg8bitType)FLREAD_IO_DWORD(doc+i); +} + +/*---------------------------------------------------------------------- + f l 8 b i t D o c W r i t e D o u b l e S h i f t + + Note : Assume data is found in 8-LSB of DiskOnChip + + Write 'count' bytes, to data bus's LSB lane with 2 address shifted. +------------------------------------------------------------------------*/ + +void FAR1 fl8bitDocWriteDoubleShift(volatile FLByte FAR0 * win,FLWord offset,FLByte FAR1* src,FLWord count) +{ + volatile FLDword FAR0 * doc = ((volatile FLDword FAR0 *)win) + offset; + register int i; + + for(i=0;( i < count );i++) + FLWRITE_IO_DWORD((FLDword)(src[i]),doc+i); +} + +/*---------------------------------------------------------------------- + f l 8 b i t D o c S e t D o u b l e S h i f t + + Note : Assume data is found in 8-LSB of DiskOnChip + + Set 'count' bytes, of data bus's LSB lane with 2 address shifted. +------------------------------------------------------------------------*/ + +void FAR1 fl8bitDocSetDoubleShift(volatile FLByte FAR0 * win,FLWord offset,FLWord count, FLByte val) +{ + volatile FLDword FAR0 * doc = ((volatile FLDword FAR0 *)win)+offset; + register int i; + + for(i=0;( i < count );i++) + FLWRITE_IO_DWORD((FLDword)val,doc+i); +} + +/*************************************************/ +/* 16-Bit DiskOnChip - No Shift */ +/*************************************************/ + +/*---------------------------------------------------------------------- + f l 1 6 b i t D o c R e a d N o S h i f t + + Note - this routine can read only even number of bytes + + Read 'count' bytes from M+ DiskOnChip with none shifted address bus. +------------------------------------------------------------------------*/ + +void FAR1 fl16bitDocReadNoShift (volatile FLByte FAR0 * win, FLWord offset, FLByte FAR1 * dest, FLWord count ) +{ + volatile FLWord FAR0 * swin = (volatile FLWord FAR0 *)( win + offset); + register int i; + register FLWord tmp; + + + if( (FLDword)dest & 0x1 ) + { + /* rare case: unaligned target buffer */ + for (i = 0; i < (int)count; ) + { + tmp = FLREAD_IO_WORD(swin); +#ifdef FL_BIG_ENDIAN + dest[i++] = (FLByte)(tmp>>8); + dest[i++] = (FLByte)tmp; +#else + dest[i++] = (FLByte)tmp; + dest[i++] = (FLByte)(tmp>>8); +#endif /* FL_BIG_ENDIAN */ + } + } + else + { /* mainstream case */ +#ifdef FL_ENVIRONMENT_VARS + /* Some memcpy implementations from none 4 bytes aligned destination + * buffer may use a for loop of single byte calls to the first 2 + * bytes. This implementation may be good for RAM, but will be + * problematic to 16bit DiskOnChip that does not have a BHE signal. + * so if the buffer is not dword aligned we would not perform memcpy */ + + if ((flPreventMemcpy == 0) && (((FLDword)dest&0x3)==0) ) + { + TFFSCPY_FROM_IO_16_BITS( dest,win + offset, count); + } + else +#endif /* FL_ENVIRONMENT_VARS */ + { /* read in short words */ + for (i = 0, count = count >> 1; i < (int)count; i++) +#ifndef FL_XSCALE_BOOT_MODE + /* while incrementing DiskOnChip offset */ + ((FLWord FAR1 *)dest)[i] = FLREAD_IO_WORD(swin+i); +#else + /* but do not increment DiskOnChip offset */ + ((FLWord FAR1 *)dest)[i] = FLREAD_IO_WORD(swin); +#endif /* FL_XSCALE_BOOT_MODE */ + } + } +} + +/*---------------------------------------------------------------------- + f l 1 6 b i t D o c W r i t e N o S h i f t + + Note - this routine can write only even number of bytes + + Write 'count' bytes to M+ DiskOnChip with none shifted address bus. +------------------------------------------------------------------------*/ + +void FAR1 fl16bitDocWriteNoShift ( volatile FLByte FAR0 * win , FLWord offset , + FLByte FAR1 * src, FLWord count ) +{ + volatile FLWord FAR0 * swin = (volatile FLWord FAR0 *)( win + offset); + register int i; + register FLWord tmp; + + if( (FLDword)src & 0x1 ) /* rare case: unaligned source buffer */ + { + for (i = 0; i < (int)count; i+=2) + { + /* tmp variable is just a precation from compiler optimizations */ +#ifdef FL_BIG_ENDIAN + tmp = ((FLWord)src[i]<<8) + (FLWord)src[i+1]; +#else + tmp = (FLWord)src[i] + ((FLWord)src[i+1]<<8); +#endif /* FL_BIG_ENDIAN */ + FLWRITE_IO_WORD(tmp,swin); + } + } + else /* mainstream case */ + { +#ifdef FL_ENVIRONMENT_VARS + if ((flPreventMemcpy == 0) && (((FLDword)src&0x3)==0)) + { + TFFSCPY_TO_IO_16_BITS(win + offset,src,count); + } + else +#endif /* FL_ENVIRONMENT_VARS */ + { + /* write in short words */ + for (i = 0, count = count >> 1; i < (int)count; i++) + /* while incrementing DiskOnChip offset */ + /* but do not increament DiskOnChip offset */ + FLWRITE_IO_WORD(((FLWord FAR1 *)src)[i],swin); + } + } +} + +/*---------------------------------------------------------------------- + f l 1 6 b i t D o c S e t N o S h i f t + + Note - this routine can write only even number of bytes + + Set 'count' bytes of M+ DiskOnChip with none shifted address bus +------------------------------------------------------------------------*/ + +void FAR1 fl16bitDocSetNoShift ( volatile FLByte FAR0 * win , FLWord offset , + FLWord count , FLByte val) +{ + volatile FLWord FAR0 * swin = (volatile FLWord FAR0 *)( win + offset); + register int i; + register FLWord tmpVal = (FLWord)val * 0x0101; + +#ifdef FL_ENVIRONMENT_VARS + if (flPreventMemcpy == 0) + { + TFFSSET_IO_16_BITS(win + offset, val, count ); + } + else +#endif /* FL_ENVIRONMENT_VARS */ + { /* write in short words */ + for (i = 0; i < (int)count; i+=2) + FLWRITE_IO_WORD(tmpVal,swin); + } +} + +/*************************************************************/ +/* 16-Bit DiskOnChip - No Shift - Only 8 bits are valid */ +/*************************************************************/ + +/*---------------------------------------------------------------------- + f l 1 6 b i t D o c R e a d N o S h i f t I g n o r e H i g h e r 8 B i t s + + Note : offset must be 16-bits aligned. + + Read 'count' bytes from M+ DiskOnChip connected with all 16 data bits, but + in interleave-1 mode , therefore only one of the 8 bits contains actual data. + The DiskOnChip is connected without an address shift. +------------------------------------------------------------------------*/ + +void FAR1 fl16bitDocReadNoShiftIgnoreHigher8bits(volatile FLByte FAR0 * win, FLWord offset, FLByte FAR1 * dest, FLWord count ) +{ + volatile FLWord FAR0 * swin = (volatile FLWord FAR0 *)( win + offset); + register int i; + + + for (i = 0; i < (int)count; i++) + { +#ifndef FL_XSCALE_BOOT_MODE + /* Read while incrementing DiskOnChip window offset */ +#ifdef FL_BIG_ENDIAN + dest[i] = (FLByte)(FLREAD_IO_WORD((volatile void FAR0 *)(swin+i))>>8); +#else + dest[i] = (FLByte)FLREAD_IO_WORD((volatile void FAR0 *)(swin+i)); +#endif /* FL_BIG_ENDIAN */ +#else + /* Read while not incrementing DiskOnChip window offset */ +#ifdef FL_BIG_ENDIAN + dest[i] = (FLByte)(FLREAD_IO_WORD(swin)>>8); +#else + dest[i] = (FLByte)(FLREAD_IO_WORD(swin)); +#endif /* FL_BIG_ENDIAN */ +#endif /* FL_XSCALE_BOOT_MODE */ + } +} + +/*---------------------------------------------------------------------- + f l 1 6 D o c W r i t e N o S h i f t I g n o r e H i g h e r 8 b i t s + + Note : offset must be 16-bits aligned. + + Write 'count' bytes to M+ DiskOnChip connected with all 16 data bits, but + in interleave-1 mode , therefore only one of the 8bits contains actual data. + The DiskOnChip is connected without an address shift. +------------------------------------------------------------------------*/ + +void FAR1 fl16bitDocWriteNoShiftIgnoreHigher8bits ( volatile FLByte FAR0 * win , FLWord offset , + FLByte FAR1 * src, FLWord count ) +{ + volatile FLWord FAR0 * swin = (volatile FLWord FAR0 *)( win + offset); + register int i; + + for (i = 0; i < (int)count; i++) + { + /* Write while not incrementing DiskOnChip window offset */ +#ifdef FL_BIG_ENDIAN + FLWRITE_IO_WORD((((FLWord)src[i])<<8),swin); +#else + FLWRITE_IO_WORD((FLWord)src[i],swin); +#endif /* FL_BIG_ENDIAN */ + } +} + +/*---------------------------------------------------------------------- + f l 1 6 D o c S e t N o S h i f t I g n o r e H i g h e r 8 b i t s + + Note : offset must be 16-bits aligned. + + Set 'count' bytes to M+ DiskOnChip connected with all 16 data bits, but + in interleave-1 mode , therefore only one of the 8bits contains actual data. + The DiskOnChip is connected without an address shift. +------------------------------------------------------------------------*/ + +void FAR1 fl16bitDocSetNoShiftIgnoreHigher8bits ( volatile FLByte FAR0 * win , FLWord offset , + FLWord count , FLByte val) +{ + volatile FLWord FAR0 * swin = (volatile FLWord FAR0 *)( win + offset ); + register int i; + register FLWord tmpVal = val * 0x0101; + + for (i = 0; i < (int)count; i++) + FLWRITE_IO_WORD(tmpVal,swin); +} + +/****************************************/ +/* 16-Bit DiskOnChip - Single Shift */ +/****************************************/ + +/*---------------------------------------------------------------------- + f l 1 6 b i t D o c R e a d S i n g l e S h i f t + + Read 'count' bytes from M+ DiskOnChip with none shifted address bus. +------------------------------------------------------------------------*/ + +void FAR1 fl16bitDocReadSingleShift (volatile FLByte FAR0 * win, FLWord offset, FLByte FAR1 * dest, FLWord count ) +{ + volatile FLDword FAR0 * swin = ((volatile FLDword FAR0 *)win) + (offset>>1); + register int i; + register FLDword tmp; + + + if( (FLDword)dest & 0x1 ) + { + /* rare case: unaligned target buffer */ + for (i = 0; i < (int)count; ) + { + tmp = FLREAD_IO_DWORD(swin); +#ifdef FL_BIG_ENDIAN + dest[i++] = (FLByte)(tmp>>24); + dest[i++] = (FLByte)(tmp>>16); +#else + dest[i++] = (FLByte)tmp; + dest[i++] = (FLByte)(tmp>>8); +#endif /* FL_BIG_ENDIAN */ + } + } + else + { /* mainstream case */ + for (i = 0, count = count >> 1; i < (int)count; i++) + { +#ifdef FL_BIG_ENDIAN + ((FLWord FAR1 *)dest)[i]=(FLWord)(FLREAD_IO_DWORD(swin+i)>>16); +#else + ((FLWord FAR1 *)dest)[i] = (FLWord)FLREAD_IO_DWORD(swin+i); +#endif /* FL_BIG_ENDIAN */ + } + } +} + +/*---------------------------------------------------------------------- + f l 1 6 b i t D o c W r i t e S i n g l e S h i f t + + Write 'count' bytes to M+ DiskOnChip with none shifted address bus. +------------------------------------------------------------------------*/ + +void FAR1 fl16bitDocWriteSingleShift ( volatile FLByte FAR0 * win , FLWord offset , + FLByte FAR1 * src, FLWord count ) +{ + volatile FLDword FAR0 * swin = ((volatile FLDword FAR0 *)win)+ (offset>>1); + register int i; + register FLDword tmp; + + if( (FLDword)src & 0x1 ) /* rare case: unaligned source buffer */ + { + for (i = 0; i < (int)count; i+=2) + { +#ifdef FL_BIG_ENDIAN + tmp = (((FLDword)src[i])<<24) + (((FLDword)src[i+1])<<16); +#else + tmp = (FLDword)src[i] + (((FLDword)src[i+1])<<8); +#endif /* FL_BIG_ENDIAN */ + FLWRITE_IO_DWORD(tmp,swin); + } + } + else /* mainstream case */ + { + for (i = 0, count = count >> 1; i < (int)count; i++) +#ifdef FL_BIG_ENDIAN + FLWRITE_IO_DWORD(((FLDword)((FLWord FAR1 *)src)[i])<<16,swin); +#else + FLWRITE_IO_DWORD(((FLDword)((FLWord FAR1 *)src)[i]),swin); +#endif /* FL_BIG_ENDIAN */ + } +} + +/*---------------------------------------------------------------------- + f l 1 6 b i t D o c S e t S i n g l e S h i f t + + Set 'count' bytes of M+ DiskOnChip with none shifted address bus +------------------------------------------------------------------------*/ + +void FAR1 fl16bitDocSetSingleShift ( volatile FLByte FAR0 * win , FLWord offset , + FLWord count , FLByte val) +{ + volatile FLDword FAR0 * swin = ((volatile FLDword FAR0 *)win)+ (offset>>1); + register int i; + register FLDword tmpVal = (FLDword)val * 0x01010101L; + + for (i = 0; i < (int)count; i+=2) + FLWRITE_IO_DWORD(tmpVal,swin); +} + + +/**************************************************************/ +/* 16-Bit DiskOnChip - Single Shift - Only 8 bits are valid */ +/**************************************************************/ + +/*---------------------------------------------------------------------- + f l 1 6 b i t D o c R e a d S i n g l e S h i f t I g n o r e H i g h e r 8 B i t s + + Note : offset must be 16-bits aligned. + + Read 'count' bytes from M+ DiskOnChip connected with all 16 data bits, but + in interleave-1 mode , therefore only one of the 8 bits contains actual data. + The DiskOnChip is connected without an address shift. +------------------------------------------------------------------------*/ + +void FAR1 fl16bitDocReadSingleShiftIgnoreHigher8bits(volatile FLByte FAR0 * win, FLWord offset, FLByte FAR1 * dest, FLWord count ) +{ + volatile FLDword FAR0* swin = ((volatile FLDword FAR0 *)win)+ (offset>>1); + register int i; + + + for (i = 0; i < (int)count; i++) + { +#ifdef FL_BIG_ENDIAN + dest[i] = (FLByte)(FLREAD_IO_DWORD(swin+i)>>24); +#else + dest[i] = (FLByte)FLREAD_IO_DWORD(swin+i); +#endif /* FL_BIG_ENDIAN */ + } +} + +/*---------------------------------------------------------------------- + f l 1 6 D o c W r i t e S i n g l e S h i f t I g n o r e H i g h e r 8 b i t s + + Note : offset must be 16-bits aligned. + + Write 'count' bytes to M+ DiskOnChip connected with all 16 data bits, but + in interleave-1 mode , therefore only one of the 8bits contains actual data. + The DiskOnChip is connected without an address shift. +------------------------------------------------------------------------*/ + +void FAR1 fl16bitDocWriteSingleShiftIgnoreHigher8bits ( volatile FLByte FAR0 * win , FLWord offset , + FLByte FAR1 * src, FLWord count ) +{ + volatile FLDword FAR0 * swin = ((volatile FLDword FAR0 *)win)+ (offset>>1); + register int i; + + for (i = 0; i < (int)count; i++) + { +#ifdef FL_BIG_ENDIAN + FLWRITE_IO_DWORD(((FLDword)src[i]<<24),swin); +#else + FLWRITE_IO_DWORD(((FLDword)src[i]),swin); +#endif /* FL_BIG_ENDIAN */ + } +} + +/*---------------------------------------------------------------------- + f l 1 6 D o c S e t S i n g l e S h i f t I g n o r e H i g h e r 8 b i t s + + Note : offset must be 16-bits aligned. + + Set 'count' bytes to M+ DiskOnChip connected with all 16 data bits, but + in interleave-1 mode , therefore only one of the 8bits contains actual data. + The DiskOnChip is connected without an address shift. +------------------------------------------------------------------------*/ + +void FAR1 fl16bitDocSetSingleShiftIgnoreHigher8bits ( volatile FLByte FAR0 * win , FLWord offset , + FLWord count , FLByte val) +{ + volatile FLDword FAR0 * swin = ((volatile FLDword FAR0 *)win) + (offset>>1); + register int i; + register FLDword tmpVal = (FLDword)val * 0x01010101L; + + for (i = 0; i < (int)count; i++) + FLWRITE_IO_DWORD(tmpVal,swin); +} + + +/**********************************************************/ +/* Set proper access type routines into the proper record */ +/**********************************************************/ + +/*----------------------------------------------------------------------*/ +/* s e t B u s T y p e O f F l a s h */ +/* */ +/* Set DiskOnChip socket / flash memory access routine. */ +/* This routine must be called by the MTD prior to any access to the */ +/* DiskOnChip */ +/* */ +/* Parameters: */ +/* flflash : Pointer to sockets flash record. */ +/* access : Type of memory access routines to install */ +/* */ +/* Note: The possible type of memory access routine are comprised of: */ +/* */ +/* Address shift: */ +/* FL_NO_ADDR_SHIFT - No address shift */ +/* FL_SINGLE_ADDR_SHIFT - Single address shift */ +/* FL_DOUBLE_ADDR_SHIFT - Double address shift */ +/* */ +/* Platform bus capabilities (access width): */ +/* FL_BUS_HAS_8BIT_ACCESS - Bus can access 8-bit */ +/* FL_BUS_HAS_16BIT_ACCESS - Bus can access 16-bit */ +/* FL_BUS_HAS_32BIT_ACCESS - Bus can access 32-bit */ +/* */ +/* Number of data bits connected to the DiskOnChip (if_cfg): */ +/* FL_8BIT_DOC_ACCESS - DiskOnChip has 8 data bits */ +/* FL_16BIT_DOC_ACCESS - DiskOnChip has 16 data bits */ +/* */ +/* Flash data bits that can be accessed in a bus cycle (interleave): */ +/* FL_8BIT_FLASH_ACCESS - 8 bits of flash per cycle */ +/* FL_16BIT_FLASH_ACCESS - 16 bits of flash per cycle */ +/* */ +/* Ignore all of the above and use user defined access routines: */ +/* FL_ACCESS_USER_DEFINED - Do not install any routine since */ +/* user already installed customer made*/ +/* routines */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ + +FLStatus FAR1 setBusTypeOfFlash(FLFlash * flash,FLDword access) +{ + /* sanity checks here if needed */ + if(flash==NULL) + { + DBG_PRINT_ERR(FLZONE_MTD,"ERROR in setBusTypeOfFlash: Flash record passed to setBusTypeOfFlash is NULL.\r\n"); + return flBadParameter; + } + + /* check if user already defined the memory access routines */ + if ((access & FL_ACCESS_USER_DEFINED) != 0) + return flOK; + + /************************************/ + /* install requested access methods */ + /************************************/ + + switch(access & FL_XX_ADDR_SHIFT_MASK) + { + case FL_NO_ADDR_SHIFT: + + flash->memWindowSize = flDocMemWinSizeNoShift; + switch(access & FL_XX_DATA_BITS_MASK) + { + case FL_8BIT_DOC_ACCESS: /* if_cfg set to 8-bits */ + + /* Make sure bus supports 8 bit access */ + if((access & FL_BUS_HAS_8BIT_ACCESS) == 0) + { + DBG_PRINT_WRN(FLZONE_MTD,"Warning: TrueFFS requires 8-bit access to DiskOnChip memory window\r\n"); + DBG_PRINT_WRN(FLZONE_MTD," for 8-bit DiskOnChip connected with no address shift.\r\n"); + return flBadParameter; + } + + flash->memWrite8bit = flWrite8bitUsing8bitsNoShift; + flash->memRead8bit = flRead8bitUsing8bitsNoShift; + flash->memRead16bit = flRead16bitUsing8bitsNoShift; + flash->memWrite16bit = flWrite16bitUsing8bitsNoShift; + flash->memRead = fl8bitDocReadNoShift; + flash->memWrite = fl8bitDocWriteNoShift; + flash->memSet = fl8bitDocSetNoShift; + break; + + case FL_16BIT_DOC_ACCESS: /* if_cfg set to 16-bits (Plus family) */ + + /* Make sure bus supports 16 bit access */ + if((access & FL_BUS_HAS_16BIT_ACCESS) == 0) + { + DBG_PRINT_WRN(FLZONE_MTD,"Warning: TrueFFS requires 16-bit access to DiskOnChip memory window\r\n"); + DBG_PRINT_WRN(FLZONE_MTD," for 16-bit DiskOnChip connected with no address shift.\r\n"); + return flBadParameter; + } + + flash->memWrite8bit = flWrite8bitUsing16bitsNoShift; + flash->memRead8bit = flRead8bitUsing16bitsNoShift; + flash->memRead16bit = flRead16bitUsing16bitsNoShift; + flash->memWrite16bit = flWrite16bitUsing16bitsNoShift; + + switch(access & FL_XX_FLASH_ACCESS_MASK) /* Interleave */ + { + case FL_8BIT_FLASH_ACCESS: /* Interleave - 1 */ + flash->memRead = fl16bitDocReadNoShiftIgnoreHigher8bits; + flash->memWrite = fl16bitDocWriteNoShiftIgnoreHigher8bits; + flash->memSet = fl16bitDocSetNoShiftIgnoreHigher8bits; + break; + case FL_16BIT_FLASH_ACCESS: /* Interleave - 2 */ + flash->memRead = fl16bitDocReadNoShift; + flash->memWrite = fl16bitDocWriteNoShift; + flash->memSet = fl16bitDocSetNoShift; + break; + default: + DBG_PRINT_ERR(FLZONE_MTD,"ERROR in setBusTypeOfFlash: TrueFFS does not support this flash access type (setBusTypeOfFlash).\r\n"); + return flBadParameter; + } + break; + + default: + DBG_PRINT_ERR(FLZONE_MTD,"ERROR in setBusTypeOfFlash: TrueFFS does not support this number of DiskOnChip data bits (setBusTypeOfFlash).\r\n"); + return flBadParameter; + } + break; + + case FL_SINGLE_ADDR_SHIFT: + + /* Install memory window size routine */ + flash->memWindowSize = flDocMemWinSizeSingleShift; + switch(access & FL_XX_DATA_BITS_MASK) + { + case FL_8BIT_DOC_ACCESS: /* if_cfg set to 8bits (or none plus family) */ + + /* Make sure bus supports 16 bit access */ + if((access & FL_BUS_HAS_16BIT_ACCESS) == 0) + { + DBG_PRINT_WRN(FLZONE_MTD,"Warning: TrueFFS requires 16-bit access to DiskOnChip memory window\r\n"); + DBG_PRINT_WRN(FLZONE_MTD," for 8-bit DiskOnChip connected with a single address shift.\r\n"); + return flBadParameter; + } + + flash->memWrite8bit = flWrite8bitUsing16bitsSingleShift; + flash->memRead8bit = flRead8bitUsing16bitsSingleShift; + flash->memWrite16bit = flWrite16bitUsing16bitsSingleShift; + flash->memRead16bit = flRead16bitUsing16bitsSingleShift; + flash->memRead = fl8bitDocReadSingleShift; + flash->memWrite = fl8bitDocWriteSingleShift; + flash->memSet = fl8bitDocSetSingleShift; + break; + + case FL_16BIT_DOC_ACCESS: /* if_cfg set to 16bits */ + + /* Make sure bus supports 32 bit access */ + if((access & FL_BUS_HAS_32BIT_ACCESS) == 0) + { + DBG_PRINT_WRN(FLZONE_MTD,"Warning: TrueFFS requires 32-bit access to DiskOnChip memory window\r\n"); + DBG_PRINT_WRN(FLZONE_MTD," for 16-bit DiskOnChip connected with a single address shift.\r\n"); + return flBadParameter; + } + + flash->memWrite8bit = flWrite8bitUsing32bitsSingleShift; + flash->memRead8bit = flRead8bitUsing32bitsSingleShift; + flash->memRead16bit = flRead16bitUsing32bitsSingleShift; + flash->memWrite16bit = flWrite16bitUsing32bitsSingleShift; + + switch(access & FL_XX_FLASH_ACCESS_MASK) /* Interleave */ + { + case FL_8BIT_FLASH_ACCESS: /* Interleave - 1 */ + flash->memRead = fl16bitDocReadSingleShiftIgnoreHigher8bits; + flash->memWrite = fl16bitDocWriteSingleShiftIgnoreHigher8bits; + flash->memSet = fl16bitDocSetSingleShiftIgnoreHigher8bits; + break; + case FL_16BIT_FLASH_ACCESS: /* Interleave - 2 */ + flash->memRead = fl16bitDocReadSingleShift; + flash->memWrite = fl16bitDocWriteSingleShift; + flash->memSet = fl16bitDocSetSingleShift; + break; + default: + DBG_PRINT_ERR(FLZONE_MTD,"ERROR in setBusTypeOfFlash: TrueFFS does not support this flash access type (setBusTypeOfFlash).\r\n"); + return flBadParameter; + } + break; + + default: + DBG_PRINT_ERR(FLZONE_MTD,"ERROR in setBusTypeOfFlash: TrueFFS does not support this number of DiskOnChip data bits (setBusTypeOfFlash).\r\n"); + return flBadParameter; + } + break; + + case FL_DOUBLE_ADDR_SHIFT: + + /* Install memory window size routine */ + flash->memWindowSize = flDocMemWinSizeDoubleShift; + switch(access & FL_XX_DATA_BITS_MASK) + { + case FL_8BIT_DOC_ACCESS: /* if_cfg set to 8bits or none plus family */ + + /* Make sure bus supports 32 bit access */ + if((access & FL_BUS_HAS_32BIT_ACCESS) == 0) + { + DBG_PRINT_WRN(FLZONE_MTD,"Warning: TrueFFS requires 32-bit access to DiskOnChip memory window\r\n"); + DBG_PRINT_WRN(FLZONE_MTD," for 8-bit DiskOnChip connected with a double address shift.\r\n"); + return flBadParameter; + } + + flash->memWrite8bit = flWrite8bitUsing32bitsDoubleShift; + flash->memRead8bit = flRead8bitUsing32bitsDoubleShift; + flash->memWrite16bit = flWrite16bitUsing32bitsDoubleShift; + flash->memRead16bit = flRead16bitUsing32bitsDoubleShift; + flash->memRead = fl8bitDocReadDoubleShift; + flash->memWrite = fl8bitDocWriteDoubleShift; + flash->memSet = fl8bitDocSetDoubleShift; + break; + + default: + DBG_PRINT_ERR(FLZONE_MTD,"ERROR in setBusTypeOfFlash: TrueFFS does not support this number of DiskOnChip data bits\r\n"); + DBG_PRINT_ERR(FLZONE_MTD," when connected with a double address shift (setBusTypeOfFlash).\r\n"); + return flBadParameter; + } + break; + + default: + DBG_PRINT_ERR(FLZONE_MTD,"ERROR in setBusTypeOfFlash: TrueFFS does not support this kind of address shifting (setBusTypeOfFlash).\r\n"); + return flBadParameter; + } + + /* Store access type in flash record */ + flash->busAccessType = access; + return flOK; +} + +#endif /* FL_NO_USE_FUNC */ + + + + + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/_docsys.h linux-2.6.30.4/drivers/block/tffs/_docsys.h --- linux-2.6.30.4-orig/drivers/block/tffs/_docsys.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/_docsys.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,205 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ + +/************************************************************************ * + * I M P O R T A N T * + * * + * The file contains DiskOnChip memory access routines and macros * + * defintions. * + * * + * In order to use the complete set of TrueFFS memory access routine * + * that allows runtime configuration of each socket access type make * + * sure the FL_NO_USE_FUNC is not defined in FLCUSTOM.H: * + * * + * If you know the exact configuration of your application you can * + * uncomment the FL_NO_USE_FUNC definition and set the proper access * + * type using the macroe defintion bellow. * + * * + ************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/3/bddoc/src/_docsys.h-arc $ + * + * Rev 1.4 Oct 22 2007 11:34:46 einat.avidan + * update copyrights header + * + * Rev 1.3 Feb 28 2007 09:53:20 einat.avidan + * No change + * + * Rev 1.2.1.1 Sep 11 2006 13:45:10 yaniv.iarovici + * Legal header added + * + * Rev 1.2.1.0 Aug 08 2006 15:55:34 Polina.Marimont + * DOC Driver 1.0 initial + */ + + +#ifndef _DOCSYS_H +#define _DOCSYS_H + +#include "defs.h" + +#ifdef FL_NO_USE_FUNC + +/*--------------------------------------------------------------------------*/ + +/* Default access layer for 16 bit configuration */ + +#ifndef flDirectWrite8BitReg +#ifdef FL_BIG_ENDIAN +#define flDirectWrite8BitReg(flash,offset,val) \ + FLWRITE_IO_WORD((((FLWord)val)<<8),((volatile FLWord FAR0 *)((flash)->win)+((offset)>>1))) +#else +#define flDirectWrite8BitReg(flash,offset,val) \ + FLWRITE_IO_WORD(((FLWord)val),((volatile FLWord FAR0 *)((flash)->win)+((offset)>>1))) +#endif /* FL_BIG_ENDIAN */ +#endif /* flDirectWrite8BitReg */ + +#ifndef flDirectWrite16BitReg +#define flDirectWrite16BitReg(flash,offset,val) \ + FLWRITE_IO_WORD(val,((volatile FLByte FAR0 *)((flash)->win)+(offset))) +#endif /* flDirectWrite16BitReg */ + +#ifndef flDirectRead8BitReg +#ifdef FL_BIG_ENDIAN +#define flDirectRead8BitReg(flash,offset) \ + (Reg8bitType)(((offset & 0x1) == 0) ? \ + ((FLREAD_IO_WORD((volatile FLWord FAR0 *)((flash)->win)+((offset)>>1))) >> 8) : \ + ((FLREAD_IO_WORD((volatile FLWord FAR0 *)((flash)->win)+((offset)>>1))) ) ) +#else +#define flDirectRead8BitReg(flash,offset) \ + (Reg8bitType)(((offset & 0x1) != 0) ? \ + ((FLREAD_IO_WORD((volatile FLWord FAR0 *)((flash)->win)+((offset)>>1))) >> 8) : \ + ((FLREAD_IO_WORD((volatile FLWord FAR0 *)((flash)->win)+((offset)>>1))) ) ) +#endif /* FL_BIG_ENDIAN */ +#endif /* flDirectRead8BitReg */ + +#ifndef flDirectRead16BitReg +#define flDirectRead16BitReg(flash,offset) \ + FLREAD_IO_WORD((flash)->win+(offset)) +#endif + +#ifndef flReadEvenNumberOfBytes +#define flReadEvenNumberOfBytes(flash,offset,dest,count) \ + TFFSCPY_FROM_IO_16_BITS( dest,((flash)->win + (offset)), count) +#endif + +#ifndef flWriteEvenNumberOfBytes +#define flWriteEvenNumberOfBytes(flash,offset,src,count) \ + TFFSCPY_TO_IO_16_BITS(((flash)->win + (offset)),src,count) +#endif + +#ifndef flRead512Bytes +#define flRead512Bytes(flash,offset,dest) flReadEvenNumberOfBytes(flash,offset,dest,512) +#endif + +#ifndef flWrite512Bytes +#define flWrite512Bytes(flash,offset,src) flWriteEvenNumberOfBytes(flash,offset,src,512) +#endif + +#ifndef flDocWindow +#define flDocWindow(flash) (0x2000) +#endif + +/*--------------------------------------------------------------------------*/ + +#else /* FL_NO_USE_FUNC */ + +/*--------------------------------------------------------------------------*/ + +/* Redirect to runtime access layer */ + +#ifndef flDirectWrite8BitReg +#define flDirectWrite8BitReg(flash,offset,val) (flash)->memWrite8bit((flash)->win,offset,val) +#endif + +#ifndef flDirectWrite16BitReg +#define flDirectWrite16BitReg(flash,offset,val) (flash)->memWrite16bit((flash)->win,offset,val) +#endif + +#ifndef flDirectRead8BitReg +#define flDirectRead8BitReg(flash,offset) (flash)->memRead8bit((flash)->win,offset) +#endif + +#ifndef flDirectRead16BitReg +#define flDirectRead16BitReg(flash,offset) (flash)->memRead16bit((flash)->win,offset) +#endif + +#ifndef flReadEvenNumberOfBytes +#define flReadEvenNumberOfBytes(flash,offset,dest,count) (flash)->memRead((flash)->win,offset,dest,count) +#endif + +#ifndef flWriteEvenNumberOfBytes +#define flWriteEvenNumberOfBytes(flash,offset,src,count) (flash)->memWrite((flash)->win,offset,src,count) +#endif + +#ifndef flRead512Bytes +#define flRead512Bytes(flash,offset,dest) flReadEvenNumberOfBytes(flash,offset,dest,512) +#endif + +#ifndef flWrite512Bytes +#define flWrite512Bytes(flash,offset,src) flWriteEvenNumberOfBytes(flash,offset,src,512) +#endif + +#ifndef flDocWindow +#define flDocWindow(flash) (flash->memWindowSize()) +#endif + +/*--------------------------------------------------------------------------*/ + +/* (private) types of DiskOnChip access configurations */ + +#define FL_8BIT_DOC_ACCESS 0x00000000L /* Has 8 data bits */ +#define FL_16BIT_DOC_ACCESS 0x00000100L /* Has 16 data bits */ +#define FL_XX_DATA_BITS_MASK 0x00000300L /* Mask of the above */ +#define FL_8BIT_FLASH_ACCESS 0x00000400L /* 8 bits of flash per cycle */ +#define FL_16BIT_FLASH_ACCESS 0x00000800L /* 16 bits of flash per cycle */ +#define FL_XX_FLASH_ACCESS_MASK 0x00000C00L /* Mask of the above */ + +#define FL_ACCESS_USER_DEFINED 0x00001000L /* User defined routines */ + +/* DiskOnChip routines prototypes */ + +extern FLStatus FAR1 setBusTypeOfFlash(FLFlash * flash,FLDword access); + +#endif /* FL_NO_USE_FUNC */ +#endif /* DOCSYS_H */ diff -urN linux-2.6.30.4-orig/drivers/block/tffs/docsys.h linux-2.6.30.4/drivers/block/tffs/docsys.h --- linux-2.6.30.4-orig/drivers/block/tffs/docsys.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/docsys.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,88 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ + +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/3/bddoc/src/docsys.h-arc $ + * + * Rev 1.5 Oct 22 2007 11:34:50 einat.avidan + * update copyrights header + * + * Rev 1.4 Sep 11 2006 13:45:18 yaniv.iarovici + * Legal header added + * + * Rev 1.3 Aug 09 2006 16:52:46 Polina.Marimont + * initial for DOC Driver 1.0 + */ + +/************************************************************************/ +/* I M P O R T A N T */ +/* */ +/* The file contains DiskOnChip memory access routines and macros */ +/* defintions. */ +/* */ +/* In order to use the complete set of TrueFFS memory access routine */ +/* that allows runtime configuration of each socket access type make */ +/* sure the FL_NO_USE_FUNC is not defined in FLCUSTOM.H. */ +/* */ +/* If you know the exact configuration of your application you can */ +/* uncomment the FL_NO_USE_FUNC definition and set the proper access */ +/* type using the macroe defintion bellow. */ +/************************************************************************/ + +#ifndef DOCSYS_H +#define DOCSYS_H + + +#ifndef FL_NO_USE_FUNC + +/* (public) types of DiskOnChip access configurations */ + +#define FL_BUS_HAS_XX_ACCESS_MASK 0x0000000FL /* Bus can access mask */ + +#define FL_XX_ADDR_SHIFT_MASK 0x000000F0L /* Address shift mask */ + +#endif /* FL_NO_USE_FUNC */ + +#include "_docsys.h" + +#endif /* DOCSYS_H */ diff -urN linux-2.6.30.4-orig/drivers/block/tffs/dosformt.h linux-2.6.30.4/drivers/block/tffs/dosformt.h --- linux-2.6.30.4-orig/drivers/block/tffs/dosformt.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/dosformt.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,443 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/3/common/dosformt.h-arc $ + * + * Rev 1.12 Oct 22 2007 11:34:50 einat.avidan + * update copyrights header + * + * Rev 1.11 Feb 28 2007 09:53:46 einat.avidan + * No change + * + * Rev 1.10.1.0 Nov 12 2006 09:47:10 Yaniv.Iarovici + * Added FAT 32 support. + * + * Rev 1.10 Sep 11 2006 13:45:18 yaniv.iarovici + * Legal header added + * + * Rev 1.9 Aug 09 2006 16:52:48 Polina.Marimont + * initial for DOC Driver 1.0 + */ + +#ifndef DOSFORMT_H +#define DOSFORMT_H + +#include "flbase.h" +#include "fltl.h" + + +#define DRIVE_NUMBER 0x80 +#define EXTENDED_BOOT_SIGNATURE 0x29 +#define BACKUP_OF_BOOT_SECTOR 6 +#define FSI_LEADING_SIGNATURE 0x41615252 +#define FSI_STRUCTURE_SIGNATURE 0x61417272 + +#ifndef FL_ROOT_DIR_ENTRIES +#define FL_ROOT_DIR_ENTRIES 512 +#endif /* FL_ROOT_DIR_ENTRIES */ + + +/* The BIOS parameter block (a part of the boot sector) */ +/* Note that this is NOT the customary definition of the BPB */ +/* (customary is to start it on 'bytesPerSector'). To avoid the */ +/* nuisance of a structure that starts at an odd offset, we add */ +/* the first 11 bytes of the boot sector here. */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + +#ifdef FL_WINDOWS_PACKING +#pragma pack(push, 1) +#endif /* FL_WINDOWS_PACKING */ + + +#else /* FL_NO_PACKED_STRUCTS_SUPPORTED */ + +#endif /* FL_NO_PACKED_STRUCTS_SUPPORTED */ + +typedef struct +{ + FLDword size; + FLByte clusterSize; +}DiskParamsTable; + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + +typedef FL_PACKED_STRUCTURES_BEFORE struct FL_PACKED_STRUCTURES_AFTER { + BPB bpb; + FLByte physicalDriveNo; + FLSByte reserved0; + FLSByte extendedBootSignature; + FLSByte volumeId[4]; + FLSByte volumeLabel[11]; + FLSByte systemId[8]; + FLSByte bootstrap[448]; + LEushort signature; +} DOSBootSector; +typedef FL_PACKED_STRUCTURES_BEFORE struct FL_PACKED_STRUCTURES_AFTER { + BPB bpb; + LEulong FAT32Size; + LEushort extFlags; + LEushort FSVer; + LEulong RootClus; + LEushort FSInfo; + LEushort bckUpBootSect; + FLByte reserved[12]; + FLByte physicalDriveNo; + FLSByte reserved0; + FLSByte extendedBootSignature; + FLSByte volumeId[4]; + FLSByte volumeLabel[11]; + FLSByte systemId[8]; + FLSByte bootstrap[420]; + LEushort signature; +} FAT32BootSector; + +typedef FL_PACKED_STRUCTURES_BEFORE struct FL_PACKED_STRUCTURES_AFTER { + LEulong FSI_LeadSig; + FLByte FSI_Reserved1[480]; + LEulong FSI_StructSig; + LEulong FSI_Free_Count; + LEulong FSI_Nxt_Free; + FLByte FSI_Reserved2[14]; + LEushort signature; +}FAT32FSInfo; +#else /* FL_NO_PACKED_STRUCTS_SUPPORTED */ + +#define FL_DOSBOOTSECTOR_BPB_OFFSET 0 /* size 36 */ +#define FL_DOSBOOTSECTOR_PHYSICAL_DRIVE_NO_OFFSET 36 /* size 1 */ +#define FL_DOSBOOTSECTOR_RESERVED0_OFFSET 37 /* size 1 */ +#define FL_DOSBOOTSECTOR_EXTENDED_BOOT_SIGNATURE_OFFSET 38 /* size 1 */ +#define FL_DOSBOOTSECTOR_VOLUME_ID_OFFSET 39 /* size 4, array */ +#define FL_DOSBOOTSECTOR_VOLUME_LABEL_OFFSET 43 /* size 11, array */ +#define FL_DOSBOOTSECTOR_SYSTEM_ID_OFFSET 54 /* size 8, array */ +#define FL_DOSBOOTSECTOR_BOOTSTRAP_OFFSET 62 /* size 448, array */ +#define FL_DOSBOOTSECTOR_SIGNATURE_OFFSET 510 /* size 2 */ +#define FL_DOSBOOTSECTOR_SIZE 512 + +#define FL_FAT32BOOTSECTOR_BPB_OFFSET 0 /* size 36 */ +#define FL_FAT32BOOTSECTOR_FAT32SIZE_OFFSET 36 /* size 4 */ +#define FL_FAT32BOOTSECTOR_EXTFLAGS_OFFSET 40 /* size 2 */ +#define FL_FAT32BOOTSECTOR_FSVER_OFFSET 42 /* size 2 */ +#define FL_FAT32BOOTSECTOR_ROOTCLUSTER_OFFSET 44 /* size 4 */ +#define FL_FAT32BOOTSECTOR_FSINFO_OFFSET 48 /* size 2 */ +#define FL_FAT32BOOTSECTOR_BCKUPBOOTSECT_OFFSET 50 /* size 2*/ +#define FL_FAT32BOOTSECTOR_RESERVED_OFFSET 52 /* size 12, array */ +#define FL_FAT32BOOTSECTOR_PHYDRIVENO_OFFSET 64 /* size 1 */ +#define FL_FAT32BOOTSECTOR_RESERVED0_OFFSET 65 /* size 1*/ +#define FL_FAT32BOOTSECTOR_EXTSIGNATURE_OFFSET 66 /* size 1 */ +#define FL_FAT32BOOTSECTOR_VOLUMEID_OFFSET 67 /* size 4, array */ +#define FL_FAT32BOOTSECTOR_VOLUMELABEL_OFFSET 71 /* size 11, array */ +#define FL_FAT32BOOTSECTOR_SYSTEMID_OFFSET 82 /* size 8 */ +#define FL_FAT32BOOTSECTOR_BOOTSTRAP_OFFSET 90 /* size 420, array */ +#define FL_FAT32BOOTSECTOR_SIGNATURE_OFFSET 510 /* size 2 */ +#define FL_FAT32BOOTSECTOR_SIZE 512 + + + +#define FL_FAT32_FSINFO_LEADSIGNATURE_OFFSET 0 /* size 4*/ +#define FL_FAT32_FSINFO_RESERVED1_OFFSET 4 /* size 480, array*/ +#define FL_FAT32_FSINFO_STRUCTSIGNATURE_OFFSET 484 /* size 4*/ +#define FL_FAT32_FSINFO_FREECOUNT_OFFSET 488 /* size 4*/ +#define FL_FAT32_FSINFO_NEXTFREE_OFFSET 492 /* size 4*/ +#define FL_FAT32_FSINFO_RESERVED2_OFFSET 496 /* size 4*/ +#define FL_FAT32_FSINFO_SIGNATURE_OFFSET 510 /* size 14, array*/ +#define FL_FAT32_FSINFO_SIZE 512 + +typedef FLByte DOSBootSector[FL_DOSBOOTSECTOR_SIZE]; +typedef FLByte FAT32BootSector[FL_FAT32BOOTSECTOR_SIZE]; +typedef FLByte FAT32FSInfo[FL_FAT32_FSINFO_SIZE]; +#endif /* FL_NO_PACKED_STRUCTS_SUPPORTED */ + + + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + +typedef FL_PACKED_STRUCTURES_BEFORE struct FL_PACKED_STRUCTURES_AFTER { + FLByte orderNum; /* 6 significant bits of LFN order number */ + Unaligned name1[5]; /* part 1 of scattered name */ + FLByte attributes; /* file attributes, must be RO, System, Hidden, Volume */ + FLByte reserved; /* must be 0 */ + FLByte checksum; /* checksum created from short form name */ + LEushort name2[6]; /* part 2 of scattered name */ + LEushort startingCluster; /* must be 0 */ + LEushort name3[2]; /* part 3 of scattered name */ +} LfnDirectoryEntry; +#else /* FL_NO_PACKED_STRUCTS_SUPPORTED */ + +#define FL_LFN_DIRECTORY_ENTRY_ORDER_NUM_OFFSET 0 /* size 1 */ +#define FL_LFN_DIRECTORY_ENTRY_NAME1_OFFSET 1 /* size 10, unaligned array of 2 */ +#define FL_LFN_DIRECTORY_ENTRY_ATTRIBUTES_OFFSET 11 /* size 1 */ +#define FL_LFN_DIRECTORY_ENTRY_RESERVED_OFFSET 12 /* size 1 */ +#define FL_LFN_DIRECTORY_ENTRY_CHECKSUM_OFFSET 13 /* size 1 */ +#define FL_LFN_DIRECTORY_ENTRY_NAME2_OFFSET 14 /* size 12, array of 2 */ +#define FL_LFN_DIRECTORY_ENTRY_STARTING_CLUSTER_OFFSET 26 /* size 2 */ +#define FL_LFN_DIRECTORY_ENTRY_NAME3_OFFSET 28 /* size 4, array of 2 */ +#define FL_LFN_DIRECTORY_ENTRY_SIZE 32 + +typedef FLByte LfnDirectoryEntry[FL_LFN_DIRECTORY_ENTRY_SIZE]; +#endif /* FL_NO_PACKED_STRUCTS_SUPPORTED */ + +/* Directory entry attribute bits */ + + + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + +typedef FL_PACKED_STRUCTURES_BEFORE struct FL_PACKED_STRUCTURES_AFTER { + /* First partition entry starts here. We do not map it as a */ + /* separate structure because it is not longword aligned */ + FLByte activeFlag; /* 80h = bootable */ + FLByte startingHead; + LEushort startingCylinderSector; + FLSByte type; + FLByte endingHead; + LEushort endingCylinderSector; + Unaligned4 startingSectorOfPartition; + Unaligned4 sectorsInPartition; + /* Partition entries 2,3 and 4 are structured as the 1st partition */ +} Partition; +#else /* FL_NO_PACKED_STRUCTS_SUPPORTED */ + +#define FL_PARTITION_ACTIVE_FLAG_OFFSET 0 /* size 1 */ +#define FL_PARTITION_STARTING_HEAD_OFFSET 1 /* size 1 */ +#define FL_PARTITION_STARTING_CYLINDER_SECTOR_OFFSET 2 /* size 2 */ +#define FL_PARTITION_TYPE_OFFSET 4 /* size 1 */ +#define FL_PARTITION_ENDING_HEAD_OFFSET 5 /* size 1 */ +#define FL_PARTITION_ENDING_CYLINDER_SECTOR_OFFSET 6 /* size 2 */ +#define FL_PARTITION_STARTING_SECTOR_OF_PARTITION_OFFSET 8 /* size 4 */ +#define FL_PARTITION_SECTORS_IN_PARTITION_OFFSET 12 /* size 4 */ +#define FL_PARTITION_SIZE 16 + +typedef FLByte Partition[FL_PARTITION_SIZE]; +#endif /* FL_NO_PACKED_STRUCTS_SUPPORTED */ + + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + +typedef FL_PACKED_STRUCTURES_BEFORE struct FL_PACKED_STRUCTURES_AFTER { + FLSByte reserved1[0x1A6]; + Unaligned4 passwordInfo[3]; /* M-Systems proprietary */ + FLSByte reserved2[0xC]; /* NT4 or NT5 signature place */ + + /* First partition entry starts here. We do not map it as a */ + /* separate structure because it is not longword aligned */ + Partition ptEntry[4]; + LEushort signature; /* = PARTITION_SIGNATURE */ +} PartitionTable; +#else /* FL_NO_PACKED_STRUCTS_SUPPORTED */ + +#define FL_PARTITION_TABLE_RESERVED1_OFFSET 0 /* size 0x1A6 */ +#define FL_PARTITION_TABLE_PASSWORD_INFO_OFFSET 422 /* size 12, unaligned array of 4 */ +#define FL_PARTITION_TABLE_RESERVED2_OFFSET 434 /* size 12, array */ +#define FL_PARTITION_TABLE_PT_ENTRY_OFFSET 446 /* size 4x16, array of partition entries */ +#define FL_PARTITION_TABLE_SIGNATURE_OFFSET 510 /* size 2 */ +#define FL_PARTITION_TABLE_SIZE 512 + +typedef FLByte PartitionTable[FL_PARTITION_TABLE_SIZE]; +#endif /* FL_NO_PACKED_STRUCTS_SUPPORTED */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + +#ifdef FL_WINDOWS_PACKING +#pragma pack(pop) +#endif /* FL_WINDOWS_PACKING */ + +#endif /* FL_NO_PACKED_STRUCTS_SUPPORTED */ + +#define PARTITION_ENTRIES 4 + + +/** Values of irFlags for flOpenFile: */ + +#define ACCESS_MODE_MASK 3 /* Mask for access mode bits */ + +/* Individual flags */ + +#define FL_ACCESS_CREATE 2 /* Create new file */ + +/* commands to flGetSetFileInfo (in addition to above) */ +#define FL_GET_DATETIME -1 /* Get date/time */ +#define FL_GET_ATTRIBUTES -2 /* Get attributes */ +#define FL_GET_CREATE_DATETIME -8 /* Get creation date/time */ + + +#ifndef LFN_NAME_MAX_CHARACTERS +#define LFN_NAME_MAX_CHARACTERS 255 +#endif /* LFN_NAME_MAX_CHARACTERS */ + +#ifndef PATH_SEGMENTS_MAX_NUM +#define PATH_SEGMENTS_MAX_NUM 10 +#endif /* PATH_SEGMENTS_MAX_NUM */ + +#ifndef PATH_CHARACTERS_MAX_NUM +#define PATH_CHARACTERS_MAX_NUM LFN_NAME_MAX_CHARACTERS +#endif /* PATH_CHARACTERS_MAX_NUM */ + +#ifndef FL_MAX_TREE_LEVELS +#define FL_MAX_TREE_LEVELS ( PATH_CHARACTERS_MAX_NUM / 2 + 1 ) +#endif /* FL_MAX_TREE_LEVELS */ + +#ifndef FL_ROOT_DIR_ENTRIES +#define FL_ROOT_DIR_ENTRIES(socket,partition) 512 +#endif /* FL_ROOT_DIR_ENTRIES */ + +#define UNICODE_CHAR_PER_LFN_ENTRY 13 + +#define SHORT_NAME_MAX_LENGTH 8 +#define EXTENSION_MAX_LENGTH 3 +#define NAME_8_3_MAX_LENGTH 12 /* "tttttttt.xxx" */ + +/* Directory entry attribute bits for internal use */ +#define ATTR_SUREFS_GEN_ATTENTION_FLAG 0x40 +#define ATTR_SUREFS_REN_ATTENTION_FLAG 0x80 +#define ATTR_SUREFS_ATTENTION_FLAG_MASK (ATTR_SUREFS_GEN_ATTENTION_FLAG | \ + ATTR_SUREFS_REN_ATTENTION_FLAG) + +#define ATTR_MASK ((unsigned char)(FL_ATTR_READ_ONLY | FL_ATTR_HIDDEN | FL_ATTR_SYSTEM | \ + FL_ATTR_VOL_LABEL | FL_ATTR_DIRECTORY | FL_ATTR_ARCHIVE)) +#define LFN_ATTRIBUTES ((unsigned char)(FL_ATTR_READ_ONLY | FL_ATTR_HIDDEN | \ + FL_ATTR_SYSTEM | FL_ATTR_VOL_LABEL)) + +#define DIRECTORY_ENTRY_SIZE 32 + +#define DIRECTORY_ENTRIES_PER_SECTOR (FL_SECTOR_SIZE / DIRECTORY_ENTRY_SIZE) +#define MAX_ROOT_DIR_SECTORS ((0x10000/DIRECTORY_ENTRIES_PER_SECTOR) - 1) + +#ifdef FS_EXP_FAT32 +/* setting this to 0xffffffff may improve performance * + * setting this to 0x0fffffff improves compatibility */ +#define FAT32_ENTRY_BITS_COMP 0x0fffffff +#endif /*FS_EXP_FAT32*/ + +#define SET_GLOBAL_ATTENTION_FLAG 0 +#ifdef FS_EXP_FAT32 +#define RESET_GLOBAL_ATTENTION_FLAG 0x0fffffff +#else /*FS_EXP_FAT32*/ +#define RESET_GLOBAL_ATTENTION_FLAG 0xffff +#endif /*FS_EXP_FAT32*/ +#define GLOBAL_ATT_FLAG_FAT_ENTRY 1 + +#define NEVER_USED_DIR_ENTRY 0 + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED +#define DELETED_DIR_ENTRY ((FLSByte) 0xe5) +#else /*FL_NO_PACKED_STRUCTS_SUPPORTED*/ +#define DELETED_DIR_ENTRY ((FLByte) 0xe5) +#endif /*FL_NO_PACKED_STRUCTS_SUPPORTED*/ + +/* FAT definitions */ + +#define FAT_FREE 0 +#define FAT_BAD_CLUSTER 0xfff7 +#ifdef FS_EXP_FAT32 +#define FAT_LAST_CLUSTER 0x0fffffff /* FAT16 values are converted */ +#else /*FS_EXP_FAT32*/ +#define FAT_LAST_CLUSTER 0xffff /* actually any of 0xfff8-0xffff */ +#endif /*FS_EXP_FAT32*/ + +/* Partition table definitions */ + +#define PARTITION_SIGNATURE 0xaa55 + +#define CYLINDER_SECTOR(cylinder,sector) ((sector) + ((cylinder & 0xff) << 8) + ((cylinder & 0x300) >> 2)) + + +#ifndef FL_MAX_PARTITION_DEPTH +#define FL_MAX_PARTITION_DEPTH 0x08 +#endif /* FL_MAX_PARTITION_DEPTH */ + +#define LFN_SHORT_NAME 0 /* for 8.3 short file name */ +#define LFN_LONG_NAME 1 /* for long file name */ +#define LFN_INVALID_SET 2 /* found invalid file name characters */ +#define SFN_LOWERCASE_NAME8 0x08 /* these 2 bit-flags are to support */ +#define SFN_LOWERCASE_EXT3 0x10 /* NT VFAT lowercase bits */ + +/*------------------------------------------------------------------------------------------- +* F L P a t h S e g m e n t +* The structure is used when analyzing path string. +* Parameters: name - address of first character of the path segment (unicode null terminated +* string. For example, for first segment of /first/second/third.ext it +* will point on "first". +* length - number of characters of the path segment +* buffSize - in case of retrieving file name this field contains size of supplied buffer +* in characters. +* get - if TRUE, this structure is used to retrieve found file name +* (getFirstFileName()). If FALSE, this structure contains file name to +* be opened/created/found (findFileName()). +*------------------------------------------------------------------------------------------*/ +typedef struct { + FLWchar FAR1 *name; + short length; + short buffSize; + FLBoolean get; + FLBoolean reserved; +} FLPathSegment; + +/*-------------------------------------------------------------------------- +* F L L f n S e a r c h +* The FLLfnSearch structer is used when searching directory by specified +* file name. +* Parameters: +* neverUsed - indicates that found at least one directory entry in sector +* that was never used. +* verifiedChars - Number of characters that successfully compared with +* file name or found in free entries in previous sector +* checksum - LFN checksum found in previous sector +* lastNum - LFN order number of last LFN entry found in previous sector +* idx - directory entry index of found entry +* status - LFN_SHORT_NAME, LFN_LONG_NAME, LFN_UPPERCASE_FOR_SHORT, +* LFN_INVALID_SET +*---------------------------------------------------------------------------*/ +typedef struct { + unsigned verifiedChars; + unsigned lastNum; + unsigned idx; + int status; + unsigned char checksum; + FLBoolean neverUsed; +} FLLfnSearch; + + + +#endif /* DOSFORMT_H */ + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/extfiltr.c linux-2.6.30.4/drivers/block/tffs/extfiltr.c --- linux-2.6.30.4-orig/drivers/block/tffs/extfiltr.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/extfiltr.c 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,717 @@ +/****************************************************************************** + * * + * Project: DOC Driver for Linux 2.4 Block device driver for mDOC H3 family * + * of devices under Linux kernel 2.4. * + * * + * Version: 1.0 * + * Email questions to: oemsupport@sandisk.com * + * Copyright (C) SanDisk IL Ltd. 1995 - 2007 * + * SanDisk IL Ltd., 7 Atir Yeda Street, Kfar Saba 44425, Israel * + * * + ****************************************************************************** + * * + * 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 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, which is set forth in the readme.txt file. * + * 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., 51 * + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + * * + * This License does not grant you any right to use the trademarks, service * + * marks or logos of SanDisk IL Ltd. or SanDisk Corporation. * + * Subject to the foregoing, SanDisk IL Ltd., for itself and on behalf of its * + * licensors, hereby reserves all intellectual property rights in the program,* + * except for the rights expressly granted in this License. * + * * + ******************************************************************************/ + +/* + * $Log$ + */ + +#include "tffsdrv.h" + + +#ifndef TFFS_DEBUG_EXTFILTER +# undef TFFS_DEBUG_DRIVER +#endif + +/* min: 0x40000 == sect>>9 == 256 blocks/group * 1024 bytes/block +typical: 0x800000 == sect>>15 == 8192 blocks/group * 1024 bytes/block +default: 0x100000 == sect>>12 == 1M */ +# define TFFS_EXTF_CACHE_STEP 12 + +#define EXTF_CACHE_MASK ((1<= 256, <= 8*blocksize */ +/* all offsets of SB/GD are including first empty block, block bitmap doesn't */ + +#ifdef TFFS_USE_RAM +# include "tffsram.h" +#else +# include "blockdev.h" +#endif + +static unsigned char pTmp[512]; + +#ifdef TFFS_DEBUG_DRIVER +static unsigned long dwSearches=0,dwSteps=0; +#endif + +unsigned char ExtReadSector(DeviceInfo*pDevice,unsigned long dwSector,unsigned char*p); +unsigned char ExtDelSector(DeviceInfo*pDevice,unsigned long dwSector,unsigned char bSectors); + +void AddSect(DeviceInfo*pDevice,SectInfo*pSect); +SectInfo*DelSect(DeviceInfo*pDevice,SectInfo*pSect); + +void CacheSect(DeviceInfo*pDevice,SectInfo*pSect); +void UncacheSect(DeviceInfo*pDevice,SectInfo*pSect); + +#define PTChanged(pSect,pData) 1 +void AddPT(DeviceInfo*pDevice,SectInfo*pSect,unsigned char*pBuff); +void DelPT(DeviceInfo*pDevice,SectInfo*pPT); + +#ifdef TFFS_DEBUG_DRIVER +unsigned char SBChanged(SectInfo*pSect,struct ext2_super_block*pSB) +{ + if(le32_to_cpu(pSB->s_log_block_size) != pSect->bSect2BlockShift-1) + { + PrintkDebug("SBChanged: s_log_block_size different: %d -> %d",(int)pSect->bSect2BlockShift-1,(int)pSB->s_log_block_size); + return 1; + } + if(le32_to_cpu(pSB->s_blocks_per_group) != pSect->dwBlocksPerBitmap) + { + PrintkDebug("SBChanged: s_blocks_per_group different: %d -> %d",(int)pSect->dwBlocksPerBitmap,(int)pSB->s_blocks_per_group); + return 1; + } + if(pSB->s_feature_compat != pSect->dwExt3Flags) + { + PrintkDebug("SBChanged: s_feature_compat different: %d -> %d",(int)pSect->dwExt3Flags,(int)pSB->s_feature_compat); + return 1; + } + PrintkDebug("SBChanged: not changed"); + return 0; +} +#else +# define SBChanged(pSect,pSB) ( ( le32_to_cpu((pSB)->s_log_block_size) != (pSect)->bSect2BlockShift-1 ) || ( le32_to_cpu((pSB)->s_blocks_per_group) != (pSect)->dwBlocksPerBitmap ) || ((pSB)->s_feature_compat!=(pSect)->dwExt3Flags)) +#endif + +void AddSB(DeviceInfo*pDevice,SectInfo*pSect,struct ext2_super_block*pSB); +void DelSB(DeviceInfo*pDevice,SectInfo*pPart); + +void AddGD(DeviceInfo*pDevice,SectInfo*pSect,struct ext2_group_desc*pGD,unsigned char bOffset); +void ProcessBB(DeviceInfo*pDevice,SectInfo*pSect,unsigned char*pOld,unsigned char*pNew,unsigned char bOffset); + +#ifdef TFFS_DEBUG_DRIVER + +void PrintSect(SectInfo*pSect,char*p) +{ + char*str; + switch(pSect->bFlag) + { + case EXTF_PT: + str="PT empty"; + break; + case EXTF_HAS_PT: + str="PT"; + break; + case EXTF_SB: + str="SB empty"; + break; + case EXTF_HAS_SB: + str="SB"; + break; + case EXTF_HAS_GD: + str="SB&GD"; + break; + case EXTF_BB: + str="BB not adjusted"; + break; + case EXTF_HAS_BB: + str="BB"; + break; + case 0: + str="last sect"; + break; + default: + str="BAD FLAG"; + } + PrintkDebug("%s: %s part %d sect %lu len %u flag %d",p,str,pSect->no,pSect->dwSector,pSect->bSectors,pSect->bFlag); +} + +void PrintAllSect(DeviceInfo*pDevice) +{ + SectInfo*pSect=&pDevice->sect[0]; + do{ + PrintSect(pSect,"LIST"); + pSect=pSect->pNext; + }while(pSect!=&pDevice->sect[0]); +} + +void Printp(unsigned char*p) +{ + int i,k; + for(i=0;i<32;i++) + { + for(k=0;k<16;k++) + printk("%2x ",*(p+((i<<4)+k))); + printk("\n"); + } +} + +#else +# define PrintAllSect(pDevice) +# define PrintSect(pSect,p) +# define Printp(p) +#endif + +void ExtFilter(DeviceInfo*pDevice,unsigned char*pBuff,unsigned long dwSector,unsigned long dwSectors) +{ + SectInfo*pSect=pDevice->pCache[dwSector>>TFFS_EXTF_CACHE_STEP]; + unsigned long dwSect=dwSector; + + PrintkDebug("ExtFilter: dev %d sec 0x%lx + 0x%lx",pDevice->diskNo,dwSector,dwSectors); + + while(dwSect=pSect->dwSector+pSect->bSectors) + pSect=pSect->pNext; + + if(dwSect>=pSect->dwSector+pSect->bSectors || dwSect+dwSectors<=pSect->dwSector) + return; + + if(dwSectdwSector) + dwSect=pSect->dwSector; + + PrintkDebug("ExtFilter: sec 0x%lx",dwSect); + +/* PrintkDebug("ExtFilter sec %lu + %lu: found %lu of %lu + %d",dwSector,dwSectors,dwSect,pSect->dwSector,pSect->bSectors); */ +/* PrintSect(pSect,"ExtFilter: found"); */ + + pData=pBuff+((dwSect-dwSector)<<9); + + switch(pSect->bFlag) + { + case EXTF_PT: + PrintkDebug("ExtFilter: EXTF_PT"); + AddPT(pDevice,pSect,pData); + dwSect=pSect->pNext->dwSector; + break; + case EXTF_HAS_PT: + PrintkDebug("ExtFilter: EXTF_HAS_PT"); + if(PTChanged(pSect,pData)) + { + DelPT(pDevice,pSect); + AddPT(pDevice,pSect,pData); + } + dwSect=pSect->pNext->dwSector; + break; + case EXTF_SB: + PrintkDebug("ExtFilter: EXTF_SB"); + AddSB(pDevice,pSect,(struct ext2_super_block*)pData); + dwSect++; + break; + case EXTF_HAS_SB: + PrintkDebug("ExtFilter: EXTF_HAS_SB"); + if(dwSect==pSect->dwSector) /* SB changed */ + { + if(SBChanged(pSect,(struct ext2_super_block*)pData)) + AddSB(pDevice,pSect,(struct ext2_super_block*)pData); + dwSect+=2; + } + else + { + if(dwSect>=pSect->dwSector+(pSect->bSect2BlockShift==3?6:2)) /* GD added */ + { + AddGD(pDevice,pSect,(struct ext2_group_desc*)pData,dwSect-(pSect->dwSector+(pSect->bSect2BlockShift==3?6:2))); + } + dwSect++; + } + break; + case EXTF_HAS_GD: /* ignore GD changes */ + PrintkDebug("ExtFilter: EXTF_HAS_GD"); + if(SBChanged(pSect,(struct ext2_super_block*)pData)) + { + DelSB(pDevice,pSect); + AddSB(pDevice,pSect,(struct ext2_super_block*)pData); + } + dwSect=pSect->pNext->dwSector; + break; + case EXTF_BB: + PrintkDebug("ExtFilter: EXTF_BB"); + /* do nothing */ + dwSect=pSect->pNext->dwSector; + break; + return; + case EXTF_HAS_BB: + PrintkDebug("ExtFilter: EXTF_HAS_BB"); + if(ExtReadSector(pDevice,dwSect,pTmp)) + ProcessBB(pDevice,pSect,pTmp,pData,dwSect-pSect->dwSector); + dwSect++; + break; +#ifdef TFFS_DEBUG_DRIVER + default: + PrintkDebug("ExtFilter: wrong case %d",pSect->bFlag); + dwSect++; +#endif + } + } + PrintkDebug("ExtFilter:exit"); +} + +void ExtFilterInit(DeviceInfo*pDevice) +{ + unsigned short wCache,wCacheSize; + + PrintkDebug("ExtFilterInit"); + + /* init first and last sectors */ + pDevice->sect[0].dwSector=0; + pDevice->sect[0].bSectors=1; + pDevice->sect[0].pParent=NULL; + pDevice->sect[0].pPrev=pDevice->sect[0].pNext=&pDevice->sect[1]; + pDevice->sect[0].bFlag=EXTF_PT; + pDevice->sect[0].dwOffset=0; + pDevice->sect[1].dwSector=0xffffffff; + pDevice->sect[1].bSectors=0; + pDevice->sect[1].pParent=NULL; + pDevice->sect[1].pPrev=pDevice->sect[1].pNext=&pDevice->sect[0]; + pDevice->sect[1].bFlag=0; + pDevice->sect[1].dwOffset=0; +#ifdef TFFS_DEBUG_DRIVER + pDevice->sect[0].no=0; + pDevice->sect[1].no=0; +#endif + + /* init hash */ + wCacheSize=(pDevice->dwSize >> TFFS_EXTF_CACHE_STEP) + 1; + PrintkDebug("ExtFilterInit: cache len %u",wCacheSize); + pDevice->pCache=KMalloc(sizeof(SectInfo*)*wCacheSize); + if(pDevice->pCache==NULL) + return; + pDevice->pCache[0]=&pDevice->sect[0]; + for(wCache=1;wCachepCache[wCache]=&pDevice->sect[1]; + + ExtReadSector(pDevice,0,pTmp); + AddPT(pDevice,&pDevice->sect[0],pTmp); + + PrintAllSect(pDevice); +} + +void ExtFilterRelease(DeviceInfo*pDevice) +{ + PrintkDebug("ExtFilterRelease: %lu times, %lu steps, average %lu",dwSearches,dwSteps,(dwSearches!=0)?dwSteps/dwSearches:0); + PrintAllSect(pDevice); + DelPT(pDevice,&pDevice->sect[0]); + if(pDevice->pCache!=NULL) + { + kfree(pDevice->pCache); + pDevice->pCache=NULL; + } +} + +void AddPT(DeviceInfo*pDevice,SectInfo*pSect,unsigned char*pBuff) +{ + SectInfo*pPT=pSect; + unsigned char*pPTData,*pPartData; + + pPTData=KMalloc(1024); + if(pPTData==NULL) + return; + memcpy(pPTData,pBuff,512); + pPartData=pPTData+512; + + while(pPT!=NULL) + { + unsigned char bPart; + SectInfo*pNextPT=NULL; + + PrintkDebug("AddPT %d",pPT->no); + + if(pPTData[510]!=0x55 || pPTData[511]!=0xaa) + { + PrintkDebug("AddPT %d: no signature",pPT->no); + pPT->bFlag=EXTF_PT; + return; + } + PrintkDebug("AddPT %d: signature found",pPT->no); + pPT->bFlag=EXTF_HAS_PT; + + for(bPart=0;bPart<4;bPart++) + { + SectInfo*pPart; + unsigned char*pData=pPTData+(446+bPart*16); + + if(*(pData+4)==0) + { + PrintkDebug("AddPT %d: empty partition %d",pPT->no,bPart); + continue; + } + + pPart=KMalloc(sizeof(SectInfo)); + if(pPart==NULL) + return; + memset(pPart,0,sizeof(SectInfo)); + + pPart->pParent=pPT; + + pPart->dwSector=*(pData+11); + pPart->dwSector<<=8; + pPart->dwSector+=*(pData+10); + pPart->dwSector<<=8; + pPart->dwSector+=*(pData+9); + pPart->dwSector<<=8; + pPart->dwSector+=*(pData+8); + + #ifdef TFFS_DEBUG_DRIVER + if(pPT->no==0) + pPart->no=bPart+1; + else + if(pPT->no<4) + pPart->no=5; + else + pPart->no=pPT->no+1; + #endif + + switch(*(pData+4)) + { + case 5: + case 0xf: + case 0x85: + /* extended partition */ + pPart->dwSector+=pPart->pParent->dwOffset; + pNextPT=pPart; /* save next extended partition */ + pPart->bSectors=1; /* partition table */ + pPart->bFlag=EXTF_PT; + pPart->dwOffset=pPT->dwOffset; + if(pPart->dwOffset==0) + pPart->dwOffset=pPart->dwSector; + AddSect(pDevice,pPart); + break; + default: + /* data partition */ + pPart->dwSector+=pPart->pParent->dwSector+2; /* offset from PT + superblock */ + pPart->bSectors=1; /* only first sector of superblock */ + pPart->bFlag=EXTF_SB; + AddSect(pDevice,pPart); + + /* add superblock */ + PrintkDebug("AddPT %d: read sector %lu for SB",pPart->no,pPart->dwSector); + ExtReadSector(pDevice,pPart->dwSector,pPartData); + AddSB(pDevice,pPart,(struct ext2_super_block*)pPartData); + + /* add group descriptors */ + if(pPart->bFlag&EXTF_HAS_SB) + { + unsigned short wGroup; + for(wGroup=0;wGroupwGroups;wGroup+=16) + { + PrintkDebug("AddPT %d: read sector %lu for GD",pPT->no,pPart->dwSector+2+(wGroup>>4)); + ExtReadSector(pDevice,pPart->dwSector+(pPart->bSect2BlockShift==3?6:2)+(wGroup>>4),pPartData); + AddGD(pDevice,pPart,(struct ext2_group_desc*)pPartData,(wGroup>>4)); + } + } + } + + PrintkDebug("AddPT: part %d added, %lu",pPart->no,pPart->dwSector); + } + pPT=pNextPT; + if(pPT!=NULL) + { + PrintkDebug("AddPT %d: read sector %lu for next PT",pPT->no,pPT->dwSector); + ExtReadSector(pDevice,pPT->dwSector,pPTData); + } + } + + kfree(pPTData); +} + +void DelPT(DeviceInfo*pDevice,SectInfo*pPT) +{ + SectInfo*pCurPT=pPT; + + while(pCurPT!=NULL) + { + SectInfo*pCurSect=pCurPT->pNext,*pNextPT=NULL;; + PrintkDebug("DelPT: part %d",pCurPT->no); + while(pCurSect!=pCurPT) + { + if(pCurSect->pParent==pCurPT) + { + PrintkDebug("DelPT: part %d flag %d",pCurSect->no,pCurSect->bFlag); + switch(pCurSect->bFlag) + { + case EXTF_PT: + case EXTF_SB: + pCurSect=DelSect(pDevice,pCurSect); + break; + case EXTF_HAS_PT: + pNextPT=pCurSect; /* save next PT */ + pCurSect=pCurSect->pNext; + break; + case EXTF_HAS_SB: + case EXTF_HAS_GD: + DelSB(pDevice,pCurSect); + pCurSect=DelSect(pDevice,pCurSect); + break; +#ifdef TFFS_DEBUG_DRIVER + default: + PrintkDebug("DelPT: wrong case"); +#endif + } + } + else + pCurSect=pCurSect->pNext; + } + if(pCurPT!=pPT) + DelSect(pDevice,pCurPT); + pCurPT=pNextPT; + } + pPT->bFlag=EXTF_PT; +} + +void AddSB(DeviceInfo*pDevice,SectInfo*pSect,struct ext2_super_block*pSB) +{ + unsigned short wGroup; + SectInfo*pBBSect; + + PrintkDebug("AddSB %d: sector %lu",pSect->no,pSect->dwSector); + /* check that is superblock */ + if( (le16_to_cpu(pSB->s_magic)!=0xef53) || (le32_to_cpu(pSB->s_creator_os)!=0) || (le32_to_cpu(pSB->s_rev_level)!=0 && le32_to_cpu(pSB->s_rev_level)!=1) ) + { + PrintkDebug("AddSB: no superblock: magic 0x%x os %d, rev %d",le16_to_cpu(pSB->s_magic),le32_to_cpu(pSB->s_creator_os),le32_to_cpu(pSB->s_rev_level)); + pSect->bFlag=EXTF_SB; + return; + } + pSect->bFlag=EXTF_HAS_SB; + + pSect->dwExt3Flags=pSB->s_feature_compat; + pSect->bSect2BlockShift=le32_to_cpu(pSB->s_log_block_size)+1; + pSect->dwBlocksPerBitmap=le32_to_cpu(pSB->s_blocks_per_group); + + /* calc no of groups */ + pSect->wGroups=(le32_to_cpu(pSB->s_blocks_count)-le32_to_cpu(pSB->s_first_data_block))/le32_to_cpu(pSB->s_blocks_per_group); + if(pSect->wGroups*le32_to_cpu(pSB->s_blocks_per_group) < le32_to_cpu(pSB->s_blocks_count)-le32_to_cpu(pSB->s_first_data_block)) + pSect->wGroups++; + PrintkDebug("AddSB %d: %u groups",pSect->no,pSect->wGroups); + + pSect->bSectors=pSect->wGroups>>4; + if(((unsigned short)pSect->bSectors)<<4 < pSect->wGroups) + pSect->bSectors++; + pSect->bSectors+=pSect->bSect2BlockShift==3?6:2; /* group descriptors sectors + 2 or 6 sect. of superblock */ + + pBBSect=KMalloc(pSect->wGroups*sizeof(SectInfo)); + if(pBBSect==NULL) + { + PrintkDebug("AddSB: kmalloc failed"); + return; + } + memset(pBBSect,0,pSect->wGroups*sizeof(SectInfo)); + pSect->bFlag=EXTF_HAS_SB; + for(wGroup=0;wGroupwGroups;wGroup++,pBBSect++) + { + pBBSect->pParent=pSect; + pBBSect->bFlag=EXTF_BB; + pBBSect->dwSector=pSect->dwSector+wGroup*((le32_to_cpu(pSB->s_blocks_per_group))<bSect2BlockShift)+1; /* the value shoul be updated in AddGD */ +#ifdef TFFS_DEBUG_DRIVER + pBBSect->no=pSect->no; +#endif + + if(wGroupwGroups-1) + { + pBBSect->dwBlocksPerBitmap=le32_to_cpu(pSB->s_blocks_per_group); + } + else /* last group */ + { + pBBSect->dwBlocksPerBitmap=le32_to_cpu(pSB->s_blocks_count)-le32_to_cpu(pSB->s_first_data_block)-le32_to_cpu(pSB->s_blocks_per_group)*(pSect->wGroups-1); + } + pBBSect->bSectors=pBBSect->dwBlocksPerBitmap>>12; + if( ((pBBSect->dwBlocksPerBitmap>>12)<<12) != pBBSect->dwBlocksPerBitmap) + pBBSect->bSectors++; + + pBBSect->dwFirstSectorOfBitmap=pSect->dwSector-2+((le32_to_cpu(pSB->s_first_data_block)+le32_to_cpu(pSB->s_blocks_per_group)*wGroup)<bSect2BlockShift); + + AddSect(pDevice,pBBSect); + } + PrintkDebug("SB %d added: sector %lu sectors %u",pSect->no,pSect->dwSector,pSect->bSectors); +} + +void DelSB(DeviceInfo*pDevice,SectInfo*pPart) +{ + SectInfo*pTmp=pPart->pNext; + + PrintkDebug("DelSB part %d",pPart->no); + + while(pTmp->bFlag&EXTF_HAS_BB || pTmp->bFlag&EXTF_BB) + { + UncacheSect(pDevice,pTmp); + pTmp=pTmp->pNext; + } + kfree(pPart->pNext); + pPart->pNext=pTmp; + pPart->bFlag=EXTF_SB; +} + + +void AddGD(DeviceInfo*pDevice,SectInfo*pSect,struct ext2_group_desc*pGD,unsigned char bOffset) +{ + unsigned short wGroup,wGroups; + SectInfo*pCurSect=pSect->pNext; + + PrintkDebug("AddGD: part %d offset %u",pSect->no,bOffset); + + wGroups=(((unsigned short)bOffset)<<4); + while(wGroups) + { + pCurSect=pCurSect->pNext; + wGroups--; + } + wGroups=pSect->wGroups-(((unsigned short)bOffset)<<4); + if(wGroups>16) + wGroups=16; + + for(wGroup=0;wGrouppNext) + { + UncacheSect(pDevice,pCurSect); + pCurSect->dwSector=((unsigned long)le32_to_cpu(pGD[wGroup].bg_block_bitmap)<bSect2BlockShift)+pSect->dwSector-2; + CacheSect(pDevice,pCurSect); + pCurSect->bFlag=EXTF_HAS_BB; + PrintkDebug("AddGD: added group %d (%d) sect %lu",wGroup,wGroup+(bOffset<<4),pCurSect->dwSector); + PrintkDebug("AddGD: 0x%lx 0x%x 0x%lx",(unsigned long)le32_to_cpu(pGD[wGroup].bg_block_bitmap),pSect->bSect2BlockShift,pSect->dwSector); + } + + /* set EXTF_HAS_GD flag to the parent sector, if it's last GD sector */ + if(((bOffset+1)<<4)>=pSect->wGroups) + { + PrintkDebug("AddGD: end group descriptors"); + pSect->bFlag=EXTF_HAS_GD; + pSect->bSectors=1; + } +} + +void ProcessBB(DeviceInfo*pDevice,SectInfo*pSect,unsigned char*pOld,unsigned char*pNew,unsigned char bOffset) +{ + unsigned long dwSectorShift=pSect->dwFirstSectorOfBitmap+(((unsigned long)bOffset)<<(pSect->pParent->bSect2BlockShift+12)); + unsigned short wBlock; + unsigned short wLastBlockInSector=pSect->dwBlocksPerBitmap-(((unsigned short)bOffset)<<12); + + /* PrintkDebug("ProcessBB %d: %lu",pSect->no,pSect->dwSector); */ + + for(wBlock=0;wBlock>5],n=((unsigned long*)pNew)[wBlock>>5]; + if(o!=n) + { + unsigned char b; + + for(b=0;b<32 && wBlock+b (n&(1L<pParent->bSect2BlockShift)+dwSectorShift,1<pParent->bSect2BlockShift); + } + } + } +} + +unsigned char ExtReadSector(DeviceInfo*pDevice,unsigned long dwSector,unsigned char*p) +{ + IOreq ioreq; + + ioreq.irHandle=pDevice->bHandle; + ioreq.irData=p; + ioreq.irLength=dwSector; + ioreq.irCount=1; + + if(flAbsRead(&ioreq)==flOK) + return 1; + else + { + PrintkDebug("ExtReadSector->flAbsRead error"); + return 0; + } +} + +unsigned char ExtDelSector(DeviceInfo*pDevice,unsigned long dwSector,unsigned char bSectors) +{ + IOreq ioreq; + + PrintkDebug("ExtDelSector: del %lu %u",dwSector,bSectors); + + ioreq.irHandle=pDevice->bHandle; + ioreq.irLength=dwSector; + ioreq.irCount=bSectors; +#ifdef DRIVER_DEBUG + if(dwSector>=pDevice->dwSize) + PrintkDebug("ExtDelSector: achtung: wrong sector 0x%lx of 0x%lx",dwSector,pDevice->dwSize); +#endif + if(flAbsDelete(&ioreq)!=flOK) + { + PrintkDebug("ExtDelSector:flAbsDelete fails"); + return 0; + } + return 1; +} + +void AddSect(DeviceInfo*pDevice,SectInfo*pSect) +{ + SectInfo*pCurSect=&pDevice->sect[1]; + +/* PrintSect(pSect,"AddSect"); */ + + while(pCurSect->pNext!=&pDevice->sect[1] && pCurSect->pNext->dwSectordwSector) + pCurSect=pCurSect->pNext; + pSect->pNext=pCurSect->pNext; + pSect->pPrev=pCurSect; + pCurSect->pNext->pPrev=pSect; + pCurSect->pNext=pSect; + CacheSect(pDevice,pSect); +} + +SectInfo*DelSect(DeviceInfo*pDevice,SectInfo*pSect) +{ + SectInfo*p=pSect->pNext; + + PrintkDebug("DelSect: %lu flag 0x%x",pSect->dwSector,pSect->bFlag); + + UncacheSect(pDevice,pSect); + pSect->pPrev->pNext=pSect->pNext; + pSect->pNext->pPrev=pSect->pPrev; + kfree(pSect); + return p; +} + +void CacheSect(DeviceInfo*pDevice,SectInfo*pSect) +{ + unsigned short wCache=pSect->dwSector>>TFFS_EXTF_CACHE_STEP; + +/* PrintkDebug("CacheSect %lu to %lu",pSect->dwSector,pSect->dwSector>>TFFS_EXTF_CACHE_STEP); */ + + while(pDevice->pCache[wCache]==pSect->pNext) + { +/* PrintkDebug("CacheSect: pCache[%u]=%lu",wCache,pSect->dwSector); */ + pDevice->pCache[wCache]=pSect; + wCache--; + } +} + +void UncacheSect(DeviceInfo*pDevice,SectInfo*pSect) +{ + unsigned short wCache=pSect->dwSector>>TFFS_EXTF_CACHE_STEP; + +/* PrintkDebug("UncacheSect %lu to %lu",pSect->dwSector,pSect->dwSector>>TFFS_EXTF_CACHE_STEP); */ + + while(pDevice->pCache[wCache]==pSect) + { +/* PrintkDebug("UncacheSect: pCache[%u]=%lu",wCache,pSect->pNext->dwSector); */ + pDevice->pCache[wCache]=pSect->pNext; + wCache--; + } +} + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/extfiltr.h linux-2.6.30.4/drivers/block/tffs/extfiltr.h --- linux-2.6.30.4-orig/drivers/block/tffs/extfiltr.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/extfiltr.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,43 @@ +/****************************************************************************** + * * + * Project: DOC Driver for Linux 2.4 Block device driver for mDOC H3 family * + * of devices under Linux kernel 2.4. * + * * + * Version: 1.0 * + * Email questions to: oemsupport@sandisk.com * + * Copyright (C) SanDisk IL Ltd. 1995 - 2007 * + * SanDisk IL Ltd., 7 Atir Yeda Street, Kfar Saba 44425, Israel * + * * + ****************************************************************************** + * * + * 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 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, which is set forth in the readme.txt file. * + * 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., 51 * + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + * * + * This License does not grant you any right to use the trademarks, service * + * marks or logos of SanDisk IL Ltd. or SanDisk Corporation. * + * Subject to the foregoing, SanDisk IL Ltd., for itself and on behalf of its * + * licensors, hereby reserves all intellectual property rights in the program,* + * except for the rights expressly granted in this License. * + * * + ******************************************************************************/ + +/* + * $Log$ + */ + +#ifndef __EXTFILTR__H__ +#define __EXTFILTR__H__ + +void ExtFilterInit(DeviceInfo*pDevice); +void ExtFilterRelease(DeviceInfo*pDevice); +void ExtFilter(DeviceInfo*pDevice,unsigned char*pBuff,unsigned long dwSector,unsigned long dwSectors); + +#endif /* __EXTFILTR__H__ */ diff -urN linux-2.6.30.4-orig/drivers/block/tffs/fatfilt.c linux-2.6.30.4/drivers/block/tffs/fatfilt.c --- linux-2.6.30.4-orig/drivers/block/tffs/fatfilt.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/fatfilt.c 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,1949 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/3/bddoc/src/fatfilt.c-arc $ + * + * Rev 1.10 Oct 22 2007 11:34:52 einat.avidan + * update copyrights header + * + * Rev 1.9 Feb 28 2007 09:53:46 einat.avidan + * No change + * + * Rev 1.8.1.1 Sep 11 2006 13:45:20 yaniv.iarovici + * Legal header added + * + * Rev 1.8.1.0 Aug 08 2006 15:55:28 Polina.Marimont + * DOC Driver 1.0 initial + */ + +/******************************************************************************* + * * + * * + * Module: FATFILT * + * * + * This module implements installable FAT12/16 filters. It supports up to * + * SOCKETS sockets, with up to FL_MAX_TL_PARTITIONS disks per socket. * + * Each disk can contain up to FL_MAX_PARTS_PER_DISK partitions on it, with * + * maximum depth of partition nesting in extended partitions equal to * + * MAX_PARTITION_DEPTH. * + * * + * In order for this module to work, disks must be abs.mounted rather then * + * mounted. In latter case, this module won't detect any of disk's * + * partitions, and won't install FAT filters. * + * * + * This module uses more then 512 bytes of stack space in case if MALLOC is * + * not enabled. * + * * + *******************************************************************************/ + +/* + * Includes + */ + +#include "fatfilt.h" +#include "blockdev.h" +#include "defs.h" + + +#if defined(FL_ABS_READ_WRITE) && !defined(FL_READ_ONLY) + + + +/* + * Module configuration + */ + +#define FL_INCLUDE_FAT_MONITOR /* undefine it to remove FAT filter code */ +#undef FL_INCLUDE_FAT32 /* define after support for FAT32 is added */ +#define FL_DEL_SECTOR_SETS /* undefine to delete single cluster at a time */ +#undef FL_DEL_SECTOR_STATS /* gather sector deletion statistics */ + + + +/* + * Defines + */ + +/* extract pointer to user's buffer from IOreq */ + +#ifdef SCATTER_GATHER +#define FLBUF(ioreq,i) (*((FLSByte FAR1 **)((ioreq)->irData) + (int)(i))) +#else +#define FLBUF(ioreq,i) ((FLSByte FAR1 *)(ioreq->irData) + (FL_SECTOR_SIZE * ((int)(i)))) +#endif + +/* extract socket# and disk# from TFFS handle */ + +#define H2S(handle) (((int)(handle)) & 0xf) +#define H2D(handle) ((((int)(handle)) >> 4) & 0xf) + +/* construct TFFS handle from socket# and disk# */ + +#define SD2H(socNo,diskNo) ((int)((((diskNo) & 0xf) << 4) | ((socNo) & 0xf))) + +/* unformatted ("raw") disk partition */ + +#define FL_RAW_PART (-1) + + + +/* + * Global vars + */ + +#ifdef FL_DEL_SECTOR_SETS +FLBoolean del_sect_sets = TRUE; /* try to delete sectors in larger sets */ +#endif + + + + +/* + * Local routines + */ + +static FLStatus reset (void); +static FLStatus discardDisk (int handle); +static FLStatus newDisk (int handle); +static FLStatus parseDisk (int handle); +static FLStatus discardDiskParts (FLffDisk *pd); +static FLStatus addDiskPart (FLffDisk *pd, int partNo); +static FLStatus addNewDiskPart (FLffDisk *pd); +static FLBoolean isPartTableWrite (FLffDisk *pd, IOreq FAR2 *ioreq); +static FLStatus isExtPartPresent (FLSByte FAR1 *buf, SectorNo *nextExtPartSec); +static FLBoolean isBPBchanged (FLffVol *pv, FLSByte FAR1 *buf); + + +#ifdef FL_INCLUDE_FAT_MONITOR + +static FLStatus partEnableFF (FLffVol* pv); +static FLStatus partFreeDelClusters (FLffVol *pv, SectorNo secNo, + FLSByte FAR1 *newFAT, IOreq *ioreq_delete); + +#endif + + + + +/* + * Local data + */ + +/* module reset flag */ + +static FLBoolean resetDone = FALSE; + +/* disks (BDTL partitions in OSAK terminology) */ + +static FLffDisk* ffDisk[FL_SOCKETS][FL_MAX_TL_PARTITIONS] = { { NULL } }; + + +#ifndef FL_MALLOC + +/* + * WARNING: Large static arrays ! + * + * sizeof(ffAllDisks[x][y]) is 64 bytes. + * sizeof(ffAllParts[x][y][z]) is 40 bytes. + * + */ + +static FLffDisk ffAllDisks[FL_SOCKETS][FL_MAX_TL_PARTITIONS]; +static FLffVol ffAllParts[FL_SOCKETS][FL_MAX_TL_PARTITIONS][FL_MAX_PARTS_PER_DISK]; + +#endif /* FL_MALLOC */ + +static const FLSByte zeroes[FL_SECTOR_SIZE] = {0}; + +#if (defined(FL_DEL_SECTOR_SETS) && defined(FL_DEL_SECTOR_STATS)) +static FLDword del_sect_stats[16] = {0}; /* sector deletion statistics */ +#endif + + + + +/* --------------------------------------------------------------------------- * + * * + * d i s c a r d D i s k P a r t s * + * * + * Discard all the partition info (if any) associated with particular disk. * + * * + * Parameters: * + * pd : disk (BDTL volume) * + * * + * Returns: * + * Always flOK. * + * * + * --------------------------------------------------------------------------- */ + +static FLStatus discardDiskParts ( FLffDisk * pd ) +{ + register int i; + + if (pd != NULL) { + + for (i = 0; i < FL_MAX_PARTS_PER_DISK; i++) { + +#ifdef FL_MALLOC + + if (pd->part[i] != NULL) { + + FL_FREE(pd->part[i]); + } +#endif + + pd->part[i] = NULL; + } + + pd->parts = 0; + } + + return flOK; +} + + + + +/* --------------------------------------------------------------------------- * + * * + * a d d D i s k P a r t * + * * + * If there is partition record #partNo associated with the disk, discard * + * this info. Attach new partition record #partNo. * + * * + * Parameters: * + * pd : disk (BDTL volume) * + * partNo : partition (0 ... FL_MAX_PARTS_PER_DISK-1) * + * * + * Returns: * + * flOK if success, otherwise respective error code * + * * + * --------------------------------------------------------------------------- */ + +static FLStatus addDiskPart ( FLffDisk * pd, + int partNo ) +{ + FLffVol * pv; + FLStatus status; + int socNo, diskNo; + + /* arg. sanity check */ + + if ((pd == NULL) || (partNo >= FL_MAX_PARTS_PER_DISK)) + return flBadDriveHandle; + + /* break TFFS handle into socket# and disk#, and do sanity check */ + + socNo = H2S(pd->handle); + diskNo = H2D(pd->handle); + + if ((socNo >= FL_SOCKETS) || (diskNo >= FL_MAX_TL_PARTITIONS)) + return flBadDriveHandle; + + status = flNotEnoughMemory; + +#ifdef FL_MALLOC + pv = (FLffVol *)FL_MALLOC( sizeof(FLffVol) ); +#else + pv = &ffAllParts[socNo][diskNo][partNo]; +#endif + + if (pv != NULL) { + + /* initialize fields in struct FLffDisk to safe values */ + + pv->handle = pd->handle; + pv->type = FL_RAW_PART; + pv->flags = 0; + pv->ffEnabled = FALSE; /* turn off FAT minitor */ + pv->sectors = (SectorNo) 0; + pv->firstFATsecNo = (SectorNo) -1; /* none */ + pv->lastFATsecNo = pv->firstFATsecNo; /* none */ + pv->firstDataSecNo = (SectorNo) 0; + pv->clusterSize = (unsigned) 0; + +#ifdef FL_MALLOC + if( pd->part[partNo] != NULL ) { + + FL_FREE(pd->part[partNo]); + pd->part[partNo] = NULL; + } +#endif + pd->part[partNo] = pv; + + status = flOK; + } + + return status; +} + + + + +/* --------------------------------------------------------------------------- * + * * + * a d d N e w D i s k P a r t * + * * + * Add one more partition record to the disk. * + * * + * Parameters: * + * pd : disk (BDTL volume) * + * * + * Returns: * + * flOK if success, otherwise respective error code * + * * + * --------------------------------------------------------------------------- */ + +static FLStatus addNewDiskPart ( FLffDisk * pd ) +{ + if (pd->parts < FL_MAX_PARTS_PER_DISK) { + + checkStatus( addDiskPart (pd, pd->parts) ); + pd->parts++; + } + + return flOK; +} + + + + +/* --------------------------------------------------------------------------- * + * * + * d i s c a r d D i s k * + * * + * Remove disk record (with all the associated partition records). * + * * + * Parameters: * + * handle : TFFS handle * + * * + * Returns: * + * flOK if success, otherwise respective error code * + * * + * --------------------------------------------------------------------------- */ + +static FLStatus discardDisk ( int handle ) +{ + int socNo, diskNo; + + /* break TFFS handle into socket# and disk#, and do sanity check */ + + socNo = H2S(handle); + diskNo = H2D(handle); + + if ((socNo >= FL_SOCKETS) || (diskNo >= FL_MAX_TL_PARTITIONS)) + return flBadDriveHandle; + + if( ffDisk[socNo][diskNo] != NULL ) { + + /* discard associated partition info */ + + (void) discardDiskParts( ffDisk[socNo][diskNo] ); + +#ifdef FL_MALLOC + + /* release disk's scratch buffer */ + + if( (ffDisk[socNo][diskNo])->buf != NULL) { + + FL_FREE( (ffDisk[socNo][diskNo])->buf ); + (ffDisk[socNo][diskNo])->buf = NULL; + } + + FL_FREE( ffDisk[socNo][diskNo] ); +#endif + + ffDisk[socNo][diskNo] = NULL; + } + + return flOK; +} + + + + +/* --------------------------------------------------------------------------- * + * * + * n e w D i s k * + * * + * Discard existing disk record (if any), and create new one. * + * * + * Parameters: * + * handle : TFFS handle * + * * + * Returns: * + * flOK if success, otherwise respective error code * + * * + * --------------------------------------------------------------------------- */ + +static FLStatus newDisk ( int handle ) +{ + int socNo, diskNo; + int i; + FLffDisk * pd; + + /* break TFFS handle into socket# and disk#, and do sanity check */ + + socNo = H2S(handle); + diskNo = H2D(handle); + + if ((socNo >= FL_SOCKETS) || (diskNo >= FL_MAX_TL_PARTITIONS)) + return flBadDriveHandle; + + /* discard current disk and associated partition info (if any) */ + + checkStatus( discardDisk(handle) ); + +#ifdef FL_MALLOC + + pd = (FLffDisk *) FL_MALLOC( sizeof(FLffDisk) ); + + if (pd == NULL) + return flNotEnoughMemory; + + /* allocate and attach disk's scratch buffer */ + + pd->buf = (FLSByte *)FL_MALLOC( FL_SECTOR_SIZE ); + + if (pd->buf == NULL) { + + FL_FREE (pd); + pd = NULL; + return flNotEnoughMemory; + } + +#else /* !FL_MALLOC */ + + pd = &ffAllDisks[socNo][diskNo]; + +#endif /* FL_MALLOC */ + + + pd->handle = handle; + pd->ffstate = flStateNotInitialized; + + /* don't know partition layout yet */ + + pd->parts = 0; + for (i = 0; i < FL_MAX_PARTS_PER_DISK; i++) + pd->part[i] = NULL; + + /* watch Master Boot Record for update */ + + pd->secToWatch = (SectorNo) 0; + + ffDisk[socNo][diskNo] = pd; + + return flOK; +} + + + + +/* --------------------------------------------------------------------------- * + * * + * i s P a r t T a b l e W r i t e * + * * + * Check if any of the sectors specified by 'ioreq' points to Master Boot * + * Record or next extended partition in the extended partitions list. * + * * + * Parameters: * + * pd : pointer to disk structure * + * ioreq : standard I/O request * + * * + * Returns: * + * TRUE if write to MBR or extended partition list is detected, otherwise * + * FALSE * + * * + * --------------------------------------------------------------------------- */ + +static FLBoolean isPartTableWrite ( FLffDisk * pd, + IOreq FAR2 * ioreq ) +{ + register FLSDword i; + + if (pd != NULL) { + + for (i = (FLSDword)0; i < ioreq->irSectorCount; i++) { + + if( (ioreq->irSectorNo + i) == (FLSDword)pd->secToWatch ) + return TRUE; + } + } + + return FALSE; +} + + + + +/* --------------------------------------------------------------------------- * + * * + * i s E x t P a r t P r e s e n t * + * * + * Check if extended partition persent in the partition table. If it is, * + * calculate the sector # where next partition table will be written to. * + * * + * Parameters: * + * buf : partition table * + * nextExtPartSec : sector where next partition table will be written to * + * * + * Returns: * + * flOK on success, otherwise error code * + * * + * --------------------------------------------------------------------------- */ + +static FLStatus isExtPartPresent ( FLSByte FAR1 * buf, + SectorNo * nextExtPartSec ) +{ + Partition FAR1 * p; + register int i; + + /* does it look like partition table ? */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + if (LE2(((PartitionTable FAR1 *) buf)->signature) != PARTITION_SIGNATURE) +#else + if (FL_GET_LE2(buf, FL_PARTITION_TABLE_SIGNATURE_OFFSET) != PARTITION_SIGNATURE) +#endif + return flBadFormat; + + /* if extended. part. present, get sector# that will contain next part. in list */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + p = &( ((PartitionTable FAR1 *) buf)->ptEntry[0] ); +#else + p = (Partition *) &FL_REF_1(buf, FL_PARTITION_TABLE_PT_ENTRY_OFFSET ); +#endif + + for (i = 0; i < FL_PART_TBL_ENTRIES; i++) { + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + if (p->type == EX_PARTIT) { + *nextExtPartSec = (SectorNo) UNAL4( p[i].startingSectorOfPartition ); +#else + if (FL_REF_1(p, FL_PARTITION_TYPE_OFFSET) == EX_PARTIT) { + *nextExtPartSec = (SectorNo) FL_GET_UNAL4(p, i* FL_PARTITION_SIZE + FL_PARTITION_STARTING_SECTOR_OF_PARTITION_OFFSET ); +#endif + return flOK; + } + } + + /* no extended partition found */ + + return flFileNotFound; +} + + + + +/* --------------------------------------------------------------------------- * + * * + * i s B P B c h a n g e d * + * * + * Check if critical fields in partition's boot sector have been changed. * + * * + * Parameters: * + * pv : disk partition (filesystem volume) * + * buf : new contents of partition's boot sector * + * * + * Returns: * + * TRUE if critical fields in BPB have been changed, otherwise FALSE * + * * + * --------------------------------------------------------------------------- */ + +static FLBoolean isBPBchanged ( FLffVol * pv, FLSByte FAR1 * buf ) +{ + BPB FAR1 * bpb; + SectorNo sectors; + SectorNo firstFATsecNo; + SectorNo lastFATsecNo; + SectorNo rootDirSecNo; + SectorNo rootDirSectors; + SectorNo sectorsPerFAT; + SectorNo firstDataSecNo; + + /* if FAT monitor already inactive on this partition, do nothing and return */ + + if (pv->ffEnabled == FALSE) + return FALSE; + + /* we only handle 512-byte sectors */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + bpb = &( ((DOSBootSector FAR1 *) buf)->bpb ); + + if( UNAL2(bpb->bytesPerSector) != FL_SECTOR_SIZE ) + return TRUE; + + /* check if 'number of sectors in partition' has been changed */ + + sectors = UNAL2( bpb->totalSectorsInVolumeDOS3 ); + + if (sectors == (SectorNo)0) + sectors = (SectorNo) LE4( bpb->totalSectorsInVolume ); +#else + bpb = (BPB FAR1 *) buf; + + if( FL_GET_UNAL2(bpb, FL_BPB_BYTES_PER_SECTOR_OFFSET) != FL_SECTOR_SIZE ) + return TRUE; + + /* check if 'number of sectors in partition' has been changed */ + + sectors = FL_GET_UNAL2(bpb, FL_BPB_TOTAL_SECTORS_IN_VOL_DOS3_OFFSET ); + + if (sectors == (SectorNo)0) + sectors = (SectorNo) FL_GET_LE4(bpb, FL_BPB_TOTAL_SECTORS_IN_VOL_OFFSET ); +#endif + + if (sectors != pv->sectors) + return TRUE; + + /* check if 'FAT's starting sector #' has been changed */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + firstFATsecNo = pv->startSecNo + (SectorNo)( LE2(bpb->reservedSectors) ); +#else + firstFATsecNo = pv->startSecNo + (SectorNo)( FL_GET_LE2(bpb, FL_BPB_RESERVED_SECTORS_OFFSET) ); +#endif + + if (firstFATsecNo != pv->firstFATsecNo) + return TRUE; + + /* check if 'FAT's ending sector #' has been changed */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + sectorsPerFAT = (SectorNo) LE2( bpb->sectorsPerFAT ); +#else + sectorsPerFAT = (SectorNo) FL_GET_LE2(bpb, FL_BPB_SECTORS_PER_FAT_OFFSET ); +#endif + + lastFATsecNo = firstFATsecNo + sectorsPerFAT - (SectorNo)1; + + if (lastFATsecNo != pv->lastFATsecNo) + return TRUE; + + /* check if 'first data sector #' has been changed */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + rootDirSecNo = firstFATsecNo + (sectorsPerFAT * bpb->noOfFATS); + + rootDirSectors = (SectorNo)1 + (SectorNo) + (((UNAL2(bpb->rootDirectoryEntries) * DIRECTORY_ENTRY_SIZE) - 1) / FL_SECTOR_SIZE); +#else + rootDirSecNo = firstFATsecNo + (sectorsPerFAT * FL_REF_1(bpb, FL_BPB_NO_OF_FATS_OFFSET)); + + rootDirSectors = (SectorNo)1 + (SectorNo) + (((FL_GET_UNAL2(bpb, FL_BPB_ROOT_DIR_ENTRIES_OFFSET) * DIRECTORY_ENTRY_SIZE) - 1) / FL_SECTOR_SIZE); +#endif + + firstDataSecNo = rootDirSecNo + rootDirSectors; + + if (firstDataSecNo != pv->firstDataSecNo) + return TRUE; + + /* check if cluster size has been changed */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + if (pv->clusterSize != bpb->sectorsPerCluster) +#else + if (pv->clusterSize != FL_REF_1(bpb, FL_BPB_SECTORS_PER_CLUSTER_OFFSET)) +#endif + return TRUE; + + return FALSE; +} + + + + +/* --------------------------------------------------------------------------- * + * * + * r e s e t * + * * + * Resets this software module to it's initial state upon boot. * + * * + * Parameters: * + * none * + * * + * Returns: * + * flOK in case of success, otherwise respective error code * + * * + * --------------------------------------------------------------------------- */ + +static FLStatus reset (void) +{ + int iSoc, iDisk; + + for (iSoc = 0; iSoc < FL_SOCKETS; iSoc++) { + + /* discard existing disk structures for that socket */ + + for (iDisk = 0; iDisk < FL_MAX_TL_PARTITIONS; iDisk++) + (void) discardDisk( SD2H(iSoc, iDisk) ); + + /* pre-allocate disk structure for first disk of every socket */ + + checkStatus( newDisk(SD2H(iSoc, 0)) ); + } + + resetDone = TRUE; + + return flOK; +} + + + + +/* --------------------------------------------------------------------------- * + * * + * p a r s e D i s k * + * * + * Read partition table(s), install and enable FAT filters on all FAT12/16 * + * partitions. * + * * + * Parameters: * + * handle : TFFS handle * + * * + * Returns: * + * flOK on success, otherwise error code * + * * + * NOTE: This routine uses disk's scratch buffer. * + * * + * --------------------------------------------------------------------------- */ + +static FLStatus parseDisk ( int handle ) +{ + int socNo, diskNo; + SectorNo extPartStartSec, sec; + int i, depth; + int type; + FLffDisk * pd; + FLffVol * pv; + Partition * pp; + IOreq ioreq; + +#ifdef FL_MALLOC + FLSByte * buf; +#else + FLSByte buf[FL_SECTOR_SIZE]; +#endif + + /* break TFFS handle into socket# and disk#, and do sanity check */ + + socNo = H2S(handle); + diskNo = H2D(handle); + + if ((socNo >= ((int) noOfSockets)) || (diskNo >= FL_MAX_TL_PARTITIONS)) + return flBadDriveHandle; + + /* if disk structure hasn't been allocated yet, do it now */ + + if (ffDisk[socNo][diskNo] == NULL) + checkStatus( newDisk(handle) ); + + pd = ffDisk[socNo][diskNo]; + +#ifdef FL_MALLOC + + /* make sure scratch buffer is available */ + + if (pd->buf == NULL) + return flBufferingError; + + buf = pd->buf; + +#endif /* FL_MALLOC */ + + /* discard obsolete disk's partition info */ + + (void) discardDiskParts (pd); + + /* read Master Boot Record */ + + ioreq.irHandle = handle; + ioreq.irSectorNo = (SectorNo) 0; + ioreq.irSectorCount = (SectorNo) 1; + ioreq.irData = (void FAR1 *) buf; + checkStatus( flAbsRead(&ioreq) ); + + /* is it MBR indeed ? */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + if (LE2(((PartitionTable *) buf)->signature) != PARTITION_SIGNATURE) +#else + if (FL_GET_LE2(buf, FL_PARTITION_TABLE_SIGNATURE_OFFSET) != PARTITION_SIGNATURE) +#endif + return flPartitionNotFound; + + /* do primary partitions only (we will do extended partitions later) */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + pp = &( ((PartitionTable *) buf)->ptEntry[0] ); +#else + pp = (Partition *) &FL_REF_1(buf, FL_PARTITION_TABLE_PT_ENTRY_OFFSET ); +#endif + + for (i = 0; i < FL_PART_TBL_ENTRIES; i++, pp++) { +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + FLByte ppType = pp->type; +#else + FLByte ppType = FL_REF_1(pp, FL_PARTITION_TYPE_OFFSET); +#endif + + if( ppType == ((FLSByte)0) ) /* skip empty slot */ + continue; + + if( ppType == ((FLSByte)EX_PARTIT) ) /* skip extended partition */ + continue; + + /* primary partition found (not necessarily FAT12/16) */ + + if( addNewDiskPart(pd) != flOK ) + break; + + pv = pd->part[pd->parts - 1]; + + /* remember partition's type, and where it starts */ + + pv->type = (int) ppType; + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + pv->startSecNo = (SectorNo) UNAL4( pp->startingSectorOfPartition ); +#else + pv->startSecNo = (SectorNo) FL_GET_UNAL4(pp, FL_PARTITION_STARTING_SECTOR_OF_PARTITION_OFFSET ); +#endif + } + + /* do extended partitions in depth */ + + for (i = 0; i < FL_PART_TBL_ENTRIES; i++) { + + /* re-read Master Boot Record */ + + ioreq.irHandle = handle; + ioreq.irSectorNo = (SectorNo) 0; + ioreq.irSectorCount = (SectorNo) 1; + ioreq.irData = (void FAR1 *) buf; + checkStatus( flAbsRead(&ioreq) ); + + /* is it MBR indeed ? */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + if (LE2(((PartitionTable *) buf)->signature) != PARTITION_SIGNATURE) +#else + if (FL_GET_LE2(buf, FL_PARTITION_TABLE_SIGNATURE_OFFSET) != PARTITION_SIGNATURE) +#endif + return flOK; + + /* pick up next extended partition in MBR */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + pp = &( ((PartitionTable *) buf)->ptEntry[i] ); + + if( pp->type == ((FLSByte)EX_PARTIT) ) { + + /* remember where extended partition starts */ + + extPartStartSec = (SectorNo) UNAL4( pp->startingSectorOfPartition ); +#else + pp = (Partition *)&FL_REF_1(buf, FL_PARTITION_TABLE_PT_ENTRY_OFFSET + FL_PARTITION_SIZE*i); + + if( FL_REF_1(pp, FL_PARTITION_TYPE_OFFSET) == ((FLSByte)EX_PARTIT) ) { + + /* remember where extended partition starts */ + + extPartStartSec = (SectorNo) FL_GET_UNAL4(pp, FL_PARTITION_STARTING_SECTOR_OF_PARTITION_OFFSET ); +#endif + + /* follow the list of partition tables */ + + sec = extPartStartSec; + + for (depth = 0; depth < FL_MAX_PARTITION_DEPTH; depth++) { + + /* read next partition table in the list */ + + ioreq.irHandle = handle; + ioreq.irSectorNo = sec; + ioreq.irSectorCount = (SectorNo) 1; + ioreq.irData = (void FAR1 *) buf; + checkStatus( flAbsRead(&ioreq) ); + + /* is it valid partition table ? */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + if (LE2(((PartitionTable *) buf)->signature) != PARTITION_SIGNATURE) +#else + if (FL_GET_LE2(buf, FL_PARTITION_TABLE_SIGNATURE_OFFSET) != PARTITION_SIGNATURE) +#endif + break; + + /* if 1st entry is zero, it's the end of part. table list */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + pp = &( ((PartitionTable *) buf)->ptEntry[0] ); + if( pp->type == ((FLSByte)0) ) +#else + pp = (Partition *) &FL_REF_1(buf, FL_PARTITION_TABLE_PT_ENTRY_OFFSET ); + if( FL_REF_1(pp, FL_PARTITION_TYPE_OFFSET) == ((FLSByte)0) ) +#endif + break; + + /* Take this partition. Remember it's type, and where it starts */ + + if( addNewDiskPart(pd) != flOK ) + break; + + pv = pd->part[pd->parts - 1]; + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + pv->type = (int) pp->type; + pv->startSecNo = + (SectorNo) UNAL4( pp->startingSectorOfPartition) + sec; +#else + pv->type = (int) FL_REF_1(pp, FL_PARTITION_TYPE_OFFSET); + pv->startSecNo = + (SectorNo) FL_GET_UNAL4(pp, FL_PARTITION_STARTING_SECTOR_OF_PARTITION_OFFSET) + sec; +#endif + + /* 2nd entry must be extended partition */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + pp = &( ((PartitionTable *) buf)->ptEntry[1] ); + if( pp->type != ((FLSByte)EX_PARTIT) ) +#else + pp = (Partition *) &FL_REF_1(buf, FL_PARTITION_TABLE_PT_ENTRY_OFFSET + FL_PARTITION_SIZE ); + if( FL_REF_1(pp, FL_PARTITION_TYPE_OFFSET) != ((FLSByte)EX_PARTIT) ) +#endif + break; + + /* sector where next part. table in the list resides */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + sec = extPartStartSec + + (SectorNo) UNAL4( pp->startingSectorOfPartition ); +#else + sec = extPartStartSec + + (SectorNo) FL_GET_UNAL4(pp, FL_PARTITION_STARTING_SECTOR_OF_PARTITION_OFFSET ); +#endif + + } /* for(depth) */ + } + } /* for(i) */ + +#ifdef FL_INCLUDE_FAT_MONITOR + + /* turn on FAT filters on FAT12/16 partition(s) */ + + if (pd->parts > 0) { + + for (i = 0; i < pd->parts; i++) { + + pv = pd->part[i]; + type = pv->type; + + /* + * WARNING : Routine partEnableFF() uses disk's scratch buffer ! + */ + + if((type == FAT12_PARTIT) || (type == FAT16_PARTIT) || (type == DOS4_PARTIT)) + partEnableFF (pv); + } + } + +#endif /* FL_INCLUDE_FAT_MONITOR */ + + /* watch for MBR (sector #0) update */ + + pd->secToWatch = (SectorNo) 0; + + pd->ffstate = flStateInitialized; + + return flOK; +} + + + + +#ifdef FL_INCLUDE_FAT_MONITOR + +/* --------------------------------------------------------------------------- * + * * + * p a r t E n a b l e F F * + * * + * Installs and enables FAT filter on partition. * + * * + * Parameters: * + * pv : disk partition (filesystem volume) * + * * + * Returns: * + * flOK on success, otherwise error code * + * * + * NOTE: This routine uses disk's scratch buffer. * + * * + * --------------------------------------------------------------------------- */ + +static FLStatus partEnableFF ( FLffVol * pv ) +{ + int socNo, diskNo; + FLffDisk * pd; + BPB * bpb; + SectorNo sectors; + SectorNo reservedSectors; + SectorNo rootDirSecNo; + SectorNo rootDirSectors; + SectorNo sectorsPerFAT; + SectorNo rootDirEntries; + unsigned maxCluster; + int partNo; + IOreq ioreq; + +#ifdef FL_MALLOC + FLSByte * buf; +#else + FLSByte buf[FL_SECTOR_SIZE]; +#endif + + DBG_PRINT_FLOW(FLZONE_FS,"Debug: (partEnableFF) checking FAT type.\r\n"); + + /* arg. sanity check */ + + if (pv == NULL) + return flBadDriveHandle; + + /* break TFFS handle into socket# and disk#, and do sanity check */ + + socNo = H2S(pv->handle); + diskNo = H2D(pv->handle); + + if ((socNo >= ((int) noOfSockets)) || (diskNo >= FL_MAX_TL_PARTITIONS)) + return flBadDriveHandle; + + /* check if 'pv' belongs to this disk */ + + pd = ffDisk[socNo][diskNo]; + + if (pd == NULL) + return flBadDriveHandle; + + for (partNo = 0; partNo < pd->parts; partNo++) { + + if (pd->part[partNo] == pv) + break; + } + + if (partNo >= pd->parts) + return flBadDriveHandle; + +#ifdef FL_MALLOC + + /* make sure scratch buffer is available */ + + if (pd->buf == NULL) + return flBufferingError; + + buf = pd->buf; + +#endif /* FL_MALLOC */ + + /* make sure FAT filter is off on this partition */ + + pv->ffEnabled = FALSE; + + pv->firstFATsecNo = (SectorNo) -1; + pv->lastFATsecNo = pv->firstFATsecNo; + pv->clusterSize = (unsigned) 0; + + /* read BPB */ + + ioreq.irHandle = pv->handle; + ioreq.irSectorNo = pv->startSecNo; + ioreq.irSectorCount = (SectorNo) 1; + ioreq.irData = (void FAR1 *) buf; + checkStatus( flAbsRead(&ioreq) ); + + /* Does it look like DOS bootsector ? */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + + bpb = &( ((DOSBootSector *) buf)->bpb ); + + if( !((bpb->jumpInstruction[0] == 0xe9) + || + ((bpb->jumpInstruction[0] == 0xeb) && (bpb->jumpInstruction[2] == 0x90)))) { +#else + + bpb = (BPB *) buf; + + if( !((FL_REF_1(bpb, FL_BPB_JUMP_INSTRUCTION_OFFSET) == 0xe9) + || + ((FL_REF_1(bpb, FL_BPB_JUMP_INSTRUCTION_OFFSET) == 0xeb) && (FL_REF_1(bpb, FL_BPB_JUMP_INSTRUCTION_OFFSET + 2) == 0x90)))) { +#endif + return flNonFATformat; + } + + /* Do we handle this sector size ? */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + if (UNAL2(bpb->bytesPerSector) != FL_SECTOR_SIZE) +#else + if (FL_GET_UNAL2(bpb, FL_BPB_BYTES_PER_SECTOR_OFFSET) != FL_SECTOR_SIZE) +#endif + return flFormatNotSupported; + + /* + * Is it a bogus BPB (leftover from previous disk partitioning) ? + * Check that there is no overlap with next partition (if one exists). + */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + sectors = UNAL2(bpb->totalSectorsInVolumeDOS3); + + if (sectors == (SectorNo)0) + sectors = (SectorNo) LE4(bpb->totalSectorsInVolume); +#else + sectors = FL_GET_UNAL2(bpb, FL_BPB_TOTAL_SECTORS_IN_VOL_DOS3_OFFSET); + + if (sectors == (SectorNo)0) + sectors = (SectorNo) FL_GET_LE4(bpb, FL_BPB_TOTAL_SECTORS_IN_VOL_OFFSET); +#endif + + if ((partNo+1 < pd->parts) && (pd->part[partNo+1] != NULL)) { + + if( sectors > (pd->part[partNo+1])->startSecNo - pv->startSecNo ) + return flNonFATformat; + } + + /* number of sectors in partition as reported by BPB */ + + pv->sectors = sectors; + + /* get number of reserved sectors from BPB, and check it's sanity */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + reservedSectors = (SectorNo) LE2(bpb->reservedSectors); +#else + reservedSectors = (SectorNo) FL_GET_LE2(bpb, FL_BPB_RESERVED_SECTORS_OFFSET); +#endif + + switch( (int)reservedSectors ) { + + case 32: /* always the case with FAT 32 */ + +#ifndef FL_INCLUDE_FAT32 + + DBG_PRINT_FLOW(FLZONE_FS,"Debug: (partEnableFF) FAT32 detected.\r\n"); + return flFormatNotSupported; +#endif + + case 1: /* must always be the case for FAT 12 and FAT16 */ + default: + + break; + } + + /* get location and size of the first FAT copy */ + + pv->firstFATsecNo = pv->startSecNo + reservedSectors; + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + sectorsPerFAT = (SectorNo) LE2(bpb->sectorsPerFAT); +#else + sectorsPerFAT = (SectorNo) FL_GET_LE2(bpb, FL_BPB_SECTORS_PER_FAT_OFFSET); +#endif + +#ifndef FL_INCLUDE_FAT32 + + if (sectorsPerFAT == 0) { /* always the case with FAT32 */ + + DBG_PRINT_FLOW(FLZONE_FS,"Debug: (partEnableFF) FAT32 detected.\r\n"); + return flFormatNotSupported; + } + +#endif + + pv->lastFATsecNo = pv->firstFATsecNo + sectorsPerFAT - (SectorNo)1; + + /* get location and size of root directory */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + rootDirSecNo = pv->firstFATsecNo + (sectorsPerFAT * bpb->noOfFATS); + + rootDirEntries = (SectorNo) UNAL2(bpb->rootDirectoryEntries); +#else + rootDirSecNo = pv->firstFATsecNo + (sectorsPerFAT * (FL_REF_1(bpb, FL_BPB_NO_OF_FATS_OFFSET))); + + rootDirEntries = (SectorNo) FL_GET_UNAL2(bpb, FL_BPB_ROOT_DIR_ENTRIES_OFFSET); +#endif + + switch (rootDirEntries) { + +#ifndef FL_INCLUDE_FAT32 + + case 0: /* always the case with FAT32 */ + + DBG_PRINT_FLOW(FLZONE_FS,"Debug: (partEnableFF) FAT32 detected.\r\n"); + return flFormatNotSupported; +#endif + + default: + + if( ((rootDirEntries * DIRECTORY_ENTRY_SIZE) % FL_SECTOR_SIZE) != 0 ) + return flNonFATformat; + break; + } + + rootDirSectors = (SectorNo)(((rootDirEntries * DIRECTORY_ENTRY_SIZE) - 1) / FL_SECTOR_SIZE) + + (SectorNo)1; + + /* get location of data area */ + + pv->firstDataSecNo = rootDirSecNo + rootDirSectors; + + /* get size of FAT cluster in sectors, and check it's sanity */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + pv->clusterSize = bpb->sectorsPerCluster; +#else + pv->clusterSize = FL_REF_1(bpb, FL_BPB_SECTORS_PER_CLUSTER_OFFSET); +#endif + + switch( (int)pv->clusterSize ) { + + case 1: case 2: case 4: case 8: case 16: case 32: case 64: case 128: + break; + + default: + return flNonFATformat; + } + + if ((pv->clusterSize << FL_SECTOR_SIZE_BITS) > (32768 /*(32 * 1024)*/)) + return flFormatNotSupported; + + /* sanity check */ + + if( (pv->lastFATsecNo < pv->firstFATsecNo) || + (pv->firstDataSecNo <= pv->lastFATsecNo) || + (pv->sectors < pv->firstDataSecNo) ) + return flNonFATformat; + + + /* decide which type of FAT is it */ + + maxCluster = (unsigned)1 + (unsigned) + ((pv->sectors - (pv->firstDataSecNo - pv->startSecNo)) / pv->clusterSize); + + if (maxCluster < 4085) { + + pv->flags |= VOLUME_12BIT_FAT; /* 12-bit FAT */ + +#ifndef FS_FAT_12BIT + + DBG_PRINT_ERR(FLZONE_FS,"ERROR - FS_FAT_12BIT must be defined.\r\n"); + return flFormatNotSupported; + +#else + + DBG_PRINT_FLOW(FLZONE_FS,"Debug: (partEnableFF) FAT12 detected.\r\n"); + +#endif /* FS_FAT_12BIT */ + } + else { + + DBG_PRINT_FLOW(FLZONE_FS,"Debug: (partEnableFF) FAT16 detected.\r\n"); + } + + /* turn on FAT filter on this partition */ + + pv->ffEnabled = TRUE; + + return flOK; +} + + + + +/* --------------------------------------------------------------------------- * + * * + * p a r t F r e e D e l C l u s t e r s * + * * + * Compare the new contents of the specified FAT sector against the old * + * one on the disk. If any freed clusters are found, issue 'sector delete' * + * calls for all sectors that are occupied by these freed clusters. * + * * + * Parameters: * + * pv : disk partition (filesystem volume) * + * secNo : abs. sector # of the FAT sector * + * newFAT : new contents of this FAT sector * + * * + * Returns: * + * flOK on success, otherwise error code * + * * + * NOTE: This routine uses disk's scratch buffer. * + * * + * --------------------------------------------------------------------------- */ + +static FLStatus partFreeDelClusters ( FLffVol * pv, + SectorNo secNo, + FLSByte FAR1 * newFAT, + IOreq * ioreq_delete ) +{ + FLffDisk * pd; + int socNo, diskNo; + FLWord oldFATentry, newFATentry; + SectorNo iSec; + unsigned firstCluster; + IOreq ioreq; + int offset; + int iPart; + +#ifdef FS_FAT_12BIT + int halfBytes; +#endif + +#ifdef FL_MALLOC + FLSByte * oldFAT; +#else + FLSByte oldFAT[FL_SECTOR_SIZE]; +#endif + + /* arg. sanity check */ + + if (pv == NULL) + return flBadDriveHandle; + + /* break TFFS handle into socket# and disk#, and do sanity check */ + + socNo = H2S(pv->handle); + diskNo = H2D(pv->handle); + + if ((socNo >= ((int) noOfSockets)) || (diskNo >= FL_MAX_TL_PARTITIONS)) + return flBadDriveHandle; + + /* check if 'pv' belongs to this disk */ + + pd = ffDisk[socNo][diskNo]; + + if (pd == NULL) + return flBadDriveHandle; + + for (iPart = 0; iPart < pd->parts; iPart++) { + + if (pd->part[iPart] == pv) + break; + } + + if (iPart >= pd->parts) + return flBadDriveHandle; + +#ifdef FL_MALLOC + + /* make sure scratch buffer is available */ + + if (pd->buf == NULL) + return flBufferingError; + + oldFAT = pd->buf; + +#endif /* FL_MALLOC */ + + /* read in the FAT sector from the disk */ + + ioreq.irHandle = pv->handle; + ioreq.irSectorNo = secNo; + ioreq.irSectorCount = 1; + ioreq.irData = (void FAR1 *) oldFAT; + checkStatus( flAbsRead(&ioreq) ); + +#ifdef FS_FAT_12BIT + + /* size of FAT entry in half-bytes */ + + halfBytes = ((pv->flags & VOLUME_12BIT_FAT) ? 3 : 4); + + /* starting cluster */ + + if (halfBytes == 3) { + + firstCluster = + ((((unsigned)(secNo - pv->firstFATsecNo)) * (2 * FL_SECTOR_SIZE)) + 2) / 3; + } + else { + + firstCluster = ((unsigned)(secNo - pv->firstFATsecNo)) * (FL_SECTOR_SIZE / 2); + } + + /* starting data sector */ + + iSec = (((SectorNo)firstCluster - 2) * pv->clusterSize) + pv->firstDataSecNo; + + offset = (firstCluster * ((unsigned) halfBytes)) & ((2 * FL_SECTOR_SIZE) - 1); + + /* + * Find if any clusters were logically deleted, and if so, delete them. + * + * NOTE: We are skipping over 12-bit FAT entries which span more than + * one sector. + */ + + for (; offset < ((2 * FL_SECTOR_SIZE) - 2); + offset += halfBytes, iSec += pv->clusterSize) { + + oldFATentry = UNAL2( *(Unaligned FAR0 *)(oldFAT + (offset / 2)) ); + newFATentry = UNAL2( *(Unaligned FAR1 *)(newFAT + (offset / 2)) ); + + if (offset & 1) { + oldFATentry >>= 4; + newFATentry >>= 4; + } + else { + if (halfBytes == 3) { + oldFATentry &= 0xfff; + newFATentry &= 0xfff; + } + } + +#else /* !FS_FAT_12BIT */ + + firstCluster = ((unsigned) (secNo - pv->firstFATsecNo) * (FL_SECTOR_SIZE / 2)); + iSec = pv->firstDataSecNo + + (((SectorNo)(firstCluster - (unsigned)2)) * pv->clusterSize); + + /* Find if any clusters were logically deleted, and if so, delete them */ + + for (offset = 0; offset < FL_SECTOR_SIZE; offset += 2, iSec += pv->clusterSize) { + + oldFATentry = LE2( *(LEushort FAR0 *)(oldFAT + offset) ); + newFATentry = LE2( *(LEushort FAR1 *)(newFAT + offset) ); + +#endif /* FS_FAT_12BIT */ + + if ((oldFATentry != FAT_FREE) && (newFATentry == FAT_FREE)) { + +#ifdef FL_DEL_SECTOR_SETS + + if (del_sect_sets == TRUE) { + + /* Rather then deleting this cluster's sectors immediately, we try to + * accumulate as many consecutive clusters as only possible before + * calling flAbsDelete(). The hope here is that the underlaying + * TL will be able to handle deletion of larger sets of + * consecutive sectors more efficiently. + */ + + if ((SectorNo)(ioreq_delete->irSectorNo + ioreq_delete->irSectorCount) == iSec) { + + ioreq_delete->irSectorCount += pv->clusterSize; + } + else { + + if (ioreq_delete->irSectorNo != (SectorNo)(-1)) { + +#ifdef FL_DEL_SECTOR_STATS + { register int x = -1, S = (int)(ioreq_delete->irSectorCount); + while (S != 0) { x++; S >>= 1; } + if ((x >= 0) && (x < (sizeof(del_sect_stats)/sizeof(del_sect_stats[0])))) { del_sect_stats[x]++; } + } +#endif + flAbsDelete (ioreq_delete); + } + + ioreq_delete->irSectorNo = iSec; + ioreq_delete->irSectorCount = pv->clusterSize; + } + } + else + +#endif /* FL_DEL_SECTOR_SETS */ + + { /* delete one FAT cluster at a time */ + + ioreq_delete->irHandle = pv->handle; + ioreq_delete->irSectorNo = iSec; + ioreq_delete->irSectorCount = pv->clusterSize; + flAbsDelete (ioreq_delete); + } + } + } + + return flOK; +} + +#endif /* FL_INCLUDE_FAT_MONITOR */ + + + + +/* --------------------------------------------------------------------------- * + * * + * f f C h e c k B e f o r e W r i t e * + * * + * Catch all the FAT updates. Detect disk partitioning operation, track it * + * to completion, re-read partition tables, and re-install FAT filters on * + * all FAT12/16 partitions. * + * * + * Parameters: * + * ioreq : standard I/O request to be checked * + * * + * Returns: * + * flOK on success, otherwise error code * + * * + * --------------------------------------------------------------------------- */ + +FLStatus ffCheckBeforeWrite ( IOreq FAR2 * ioreq ) +{ + int socNo, diskNo; + FLffDisk * pd; + FLffVol * pv; + FLSDword iSec; + int iPart; + IOreq ioreq2; + FLSByte FAR1 * usrBuf; + + /* if module hasn't been reset yet, do it now */ + + if (resetDone == FALSE) + (void) reset(); + + /* break TFFS handle into socket# and disk#, and do sanity check */ + + socNo = H2S(ioreq->irHandle); + diskNo = H2D(ioreq->irHandle); + + if ((socNo >= ((int) noOfSockets)) || (diskNo >= FL_MAX_TL_PARTITIONS)) + return flBadDriveHandle; + + /* if disk structure hasn't been allocated yet, do it now */ + + if (ffDisk[socNo][diskNo] == NULL) + checkStatus( newDisk((int)ioreq->irHandle) ); + + pd = ffDisk[socNo][diskNo]; + + /* read partition table(s) and install FAT filters is needed */ + + if (pd->ffstate == flStateNotInitialized) + checkStatus( parseDisk((int)ioreq->irHandle) ); + + /* catch writes to MBR, and track the whole disk partitioning operations */ + + while( isPartTableWrite(pd, ioreq) == TRUE ) { + + /* disk re-partitioning is in progress */ + + if( pd->secToWatch == (SectorNo)0 ) { + + /* it's write to MBR, so trash BPBs in all disk's partitions */ + + if (pd->parts > 0) { + + for (iPart = 0; iPart < pd->parts; iPart++) { + + ioreq2.irHandle = ioreq->irHandle; + ioreq2.irSectorNo = (pd->part[iPart])->startSecNo; + ioreq2.irSectorCount = (SectorNo) 1; + ioreq2.irData = (void FAR1 *) zeroes; + (void) flAbsWrite(&ioreq2); + } + } + } + + /* keep FAT filters disabled while disk partitioning is in progress */ + + pd->ffstate = flStateInitInProgress; + + /* partition table which is about to be written to disk */ + + usrBuf = FLBUF( ioreq, (pd->secToWatch - ioreq->irSectorNo) ); + + switch( isExtPartPresent(usrBuf, &(pd->secToWatch)) ) { + + case flOK: + + /* + * Found valid partition table with extended partition. + * The pd->secToWatch has been updated to point to the + * sector where next partition table will be written to. + */ + continue; + + case flFileNotFound: + + /* + * Valid partition table, but no extended partition in it. + * Partitioning has been completed. Set pd->ffstate to + * 'flStateNotInitialized' to initiate parsing of partition + * table(s) and FAT filter installation next time this routine + * is called. + */ + + pd->ffstate = flStateNotInitialized; + break; + + case flBadFormat: + default: + + /* No valid partition table. */ + + break; + } + + return flOK; + } + +#ifdef FL_INCLUDE_FAT_MONITOR + + /* check for FAT update */ + + if (pd->ffstate == flStateInitialized) { + +#ifdef FL_DEL_SECTOR_SETS + + if (del_sect_sets == TRUE) { + + ioreq2.irHandle = ioreq->irHandle; + ioreq2.irSectorNo = (FLSDword)(-1); + ioreq2.irSectorCount = 0; + } +#endif + + /* NOTE: We can handle 'write' request that spans disk partition boundaries */ + + for (iSec = ioreq->irSectorNo; + iSec < (ioreq->irSectorNo + ioreq->irSectorCount); iSec++) { + + for (iPart = 0; iPart < pd->parts; iPart++) { + + pv = pd->part[iPart]; + + /* we monitor only FAT12/16 partitions */ + + if ((pv->type != FAT12_PARTIT) && (pv->type != FAT16_PARTIT) && + (pv->type != DOS4_PARTIT)) + continue; + + /* FAT filters can be disabled on individual partitions */ + + if (pv->ffEnabled != TRUE) + continue; + + if (iSec == (FLSDword)pv->startSecNo) { + + /* partition's boot sector is being updated */ + + usrBuf = FLBUF( ioreq, (iSec - ioreq->irSectorNo) ); + + if( isBPBchanged(pv, usrBuf) == TRUE ) { + + /* + * Critical fields in partition's boot sector have been changed. + * Turn off FAT monitor on this partition. + */ + + pv->ffEnabled = FALSE; + + DBG_PRINT_FLOW(FLZONE_FS,"Debug: (ffCheckBeforeWrite) BPB update detected.\r\n"); + continue; + } + } + + if ((iSec >= (FLSDword)pv->firstFATsecNo) && (iSec <= (FLSDword)pv->lastFATsecNo)) { + + /* + * Compare new and old contents of FAT sectors(s). If freed + * sectors are detected, add then to ioreq2. + */ + + usrBuf = FLBUF( ioreq, (iSec - ioreq->irSectorNo) ); + + checkStatus( partFreeDelClusters(pv, iSec, usrBuf, &ioreq2) ); + } + } /* for(iPart) */ + } /* for(iSec) */ + +#ifdef FL_DEL_SECTOR_SETS + + if ((del_sect_sets == TRUE) && (ioreq2.irSectorNo != (SectorNo)(-1))) { + +#ifdef FL_DEL_SECTOR_STATS + { register int x = -1, S = (int)(ioreq2.irSectorCount); + while (S != 0) { x++; S >>= 1; } + if ((x >= 0) && (x < (sizeof(del_sect_stats)/sizeof(del_sect_stats[0])))) { del_sect_stats[x]++; } + } +#endif + flAbsDelete (&ioreq2); + } + +#endif /* FL_DEL_SECTOR_SETS */ + } + +#endif /* FL_INCLUDE_FAT_MONITOR */ + + return flOK; +} + + + + +/* --------------------------------------------------------------------------- * + * * + * f l f f C o n t r o l * + * * + * Enable/disable/install FAT filters. See comments inside the routine for * + * the list of supported operations. * + * * + * Parameters: * + * handle : TFFS handle * + * partNo : partition # (0 .. FL_MAX_PARTS_PER_DISK) * + * state : see list of supported operations below * + * * + * Returns: * + * flOK on success, otherwise error code * + * * + * --------------------------------------------------------------------------- * + * * + * The following FAT monitor control requests are supported: * + * * + * state : flStateNotInitialized * + * partNo : [0 ... pd->parts-1] * + * action : turn off FAT monitor on specified partition * + * * + * state : flStateNotInitialized * + * partNo : < 0 * + * action : turn off FAT monitor on all partitions * + * * + * state : flStateInitialized * + * partNo : [0 ... pd->parts-1] * + * action : if FAT monitor has been installed on specified partition, * + * turn it on * + * * + * state : flStateInitInProgress * + * partNo : ignored * + * action : re-read partition table(s), and install FAT filters on all * + * partitions * + * * + * --------------------------------------------------------------------------- */ + +FLStatus flffControl ( int handle, + int partNo, + FLState state ) +{ + int socNo, diskNo; + FLffDisk * pd; + int i; + FLStatus status; + + /* if module hasn't been reset yet, do it now */ + + if (resetDone == FALSE) + (void) reset(); + + /* break TFFS handle into socket# and disk#, and do sanity check */ + + socNo = H2S(handle); + diskNo = H2D(handle); + + if ((socNo >= ((int) noOfSockets)) || (diskNo >= FL_MAX_TL_PARTITIONS)) + return flBadDriveHandle; + + /* if disk structure hasn't been allocated yet, do it now */ + + if (ffDisk[socNo][diskNo] == NULL) + checkStatus( newDisk(handle) ); + + pd = ffDisk[socNo][diskNo]; + + /* abort if disk re-partitioning is in progress */ + + if (pd->ffstate == flStateInitInProgress) + return flDriveNotReady; + + /* read partition table(s) and install FAT filters is needed */ + + if (pd->ffstate == flStateNotInitialized) { + + if (state == flStateNotInitialized) + return flOK; + + checkStatus( parseDisk(handle) ); + } + + /* check 'partNo' arguement for sanity */ + + if ((partNo >= pd->parts) || (partNo >= FL_MAX_PARTS_PER_DISK)) + return flBadDriveHandle; + + /* do requested operation */ + + status = flBadParameter; + + switch (state) { + + case flStateInitInProgress: + + /* read partition table(s), install FAT filters on all partitions */ + + pd->ffstate = flStateNotInitialized; + status = parseDisk(handle); + break; + + case flStateNotInitialized: + + /* turn off FAT monitor */ + + if (partNo < 0) { /* all partitions */ + + for (i = 0; i < FL_MAX_PARTS_PER_DISK; i++) { + + if (pd->part[i] != NULL) + (pd->part[i])->ffEnabled = FALSE; + } + } + else { /* specified partition */ + + if (pd->part[partNo] != NULL) + (pd->part[partNo])->ffEnabled = FALSE; + } + status = flOK; + break; + +#ifdef FL_INCLUDE_FAT_MONITOR + + case flStateInitialized: + + /* turn on FAT monitor */ + + if ((pd->ffstate == flStateInitialized) && (partNo >= 0)) { + + if (pd->part[partNo] != NULL) { + + switch( (pd->part[partNo])->type ) { + + case FAT12_PARTIT: + case FAT16_PARTIT: + case DOS4_PARTIT: + (pd->part[partNo])->ffEnabled = TRUE; + status = flOK; + break; + + case FL_RAW_PART: + DBG_PRINT_ERR(FLZONE_FS,"ERROR - can't ctrl non-existent partition.\r\n"); + break; + + default: + DBG_PRINT_ERR(FLZONE_FS,"ERROR - can't ctrl non-FAT12/16 partition.\r\n"); + break; + } + } + } + break; + +#endif /* FL_INCLUDE_FAT_MONITOR */ + + } /* switch(state) */ + + return status; +} + + + + +/* --------------------------------------------------------------------------- * + * * + * f l f f I n f o * + * * + * Obtain complete partition info for specified disk. * + * * + * Parameters: * + * handle : TFFS handle * + * * + * Returns: * + * NULL if error, otherwise pointer to partitioning info * + * * + * --------------------------------------------------------------------------- */ + +FLffDisk * flffInfo ( int handle ) +{ + int socNo, diskNo; + FLffDisk * pd; + + /* if module hasn't been reset yet, do it now */ + + if (resetDone == FALSE) + (void) reset(); + + /* break TFFS handle into socket# and disk#, and do sanity check */ + + socNo = H2S(handle); + diskNo = H2D(handle); + + if ((socNo >= ((int) noOfSockets)) || (diskNo >= FL_MAX_TL_PARTITIONS)) + return NULL; + + /* if disk structure hasn't been allocated yet, do it now */ + + if (ffDisk[socNo][diskNo] == NULL) { + + if( newDisk(handle) != flOK ) + return NULL; + } + + pd = ffDisk[socNo][diskNo]; + + /* read partition table(s) and install FAT filters is needed */ + + if (pd->ffstate == flStateNotInitialized) { + + if( parseDisk(handle) != flOK ) + return NULL; + } + + return pd; +} + + + +#endif /* FL_ABS_READ_WRITE && FL_READ_ONLY */ + + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/fatfilt.h linux-2.6.30.4/drivers/block/tffs/fatfilt.h --- linux-2.6.30.4-orig/drivers/block/tffs/fatfilt.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/fatfilt.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,185 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/3/bddoc/src/fatfilt.h-arc $ + * + * Rev 1.5 Oct 22 2007 11:34:52 einat.avidan + * update copyrights header + * + * Rev 1.4 Sep 11 2006 13:45:20 yaniv.iarovici + * Legal header added + * + * Rev 1.3 Aug 09 2006 16:52:48 Polina.Marimont + * initial for DOC Driver 1.0 + */ + +/******************************************************************************* + * * + * Module: FATFILT * + * * + * This module implements installable FAT12/16 filters. It supports up to * + * SOCKETS sockets, with up to FL_MAX_DISKS_PER_SOCKET disks per socket. * + * Each disk can contain up to FL_MAX_PARTS_PER_DISK partitions on it, with * + * maximum depth of partition nesting in extended partitions equal to * + * MAX_PARTITION_DEPTH. * + * * + * In order for this module to work, disks must be abs.mounted rather then * + * mounted. In latter case, this module won't detect any of disk's * + * partitions, and won't install FAT filters. * + * * + * This module uses more then 512 bytes of stack space in case if MALLOC is * + * not enabled. * + * * + *******************************************************************************/ + + +#ifndef FLFF_H +#define FLFF_H + + + +#include "dosformt.h" + + + +/* number of entries in disk's partition table */ + +#define FL_PART_TBL_ENTRIES 4 + +/* max number of partitions (filesystem volumes) per disk */ + +#define FL_MAX_PARTS_PER_DISK (FL_PART_TBL_ENTRIES + FL_MAX_PARTITION_DEPTH) + + + + +/* + * Generic 'initialization status' type + */ + +typedef enum { + + flStateNotInitialized = 0, + flStateInitInProgress = 1, + flStateInitialized = 2 + + } FLState; + + +/* + * Disk partition (filesystem volume). Multiple partitions are allowed + * on the disk. + */ + +typedef struct { + + int handle; /* disk's TFFS handle */ + int type; /* FAT16_PARTIT */ + int flags; /* VOLUME_12BIT_FAT etc. */ + FLBoolean ffEnabled; /* FAT filter is enabled on that part. */ + SectorNo startSecNo; /* sectorNo where partition starts */ + SectorNo sectors; /* (info) total sectors in partition */ + SectorNo firstFATsecNo; /* sectorNo of 1st sector of 1st FAT */ + SectorNo lastFATsecNo; /* sectorNo of last sector of 1st FAT */ + SectorNo firstDataSecNo; + unsigned clusterSize; /* Cluster size in sectors */ + +} FLffVol; + + +/* + * Disk with multiple partitions. Multiple disks are allowed on socket. + */ + +typedef struct { + + int handle; /* disk's TFFS handle */ + FLState ffstate; /* FAT filter init. state */ + int parts; /* total FAT12/16 partitions found */ + FLffVol * part[FL_MAX_PARTS_PER_DISK]; + SectorNo secToWatch; /* used to track disk partitioning */ + FLSByte * buf; /* scratch buffer */ + +} FLffDisk; + + +/* + * Master Boot Record/Extended Boot Record of the disk + */ + +typedef struct { + + FLSByte reserved[0x1be]; + + struct { + FLByte activeFlag; /* 80h = bootable */ + FLByte startingHead; + LEushort startingCylinderSector; + FLSByte type; + FLByte endingHead; + LEushort endingCylinderSector; + Unaligned4 startingSectorOfPartition; + Unaligned4 sectorsInPartition; + } parts [FL_PART_TBL_ENTRIES]; + + LEushort signature; /* = PARTITION_SIGNATURE */ + +} flMBR; + + + + +/* + * FAT Filter API + */ + +#if defined(FL_ABS_READ_WRITE) && !defined(FL_READ_ONLY) + + extern FLStatus ffCheckBeforeWrite (IOreq FAR2 *ioreq); + extern FLStatus flffControl (int devNo, int partNo, FLState state); + extern FLffDisk* flffInfo (int devNo); + +#endif + +#endif /* FLFF_H */ + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/flbase.c linux-2.6.30.4/drivers/block/tffs/flbase.c --- linux-2.6.30.4-orig/drivers/block/tffs/flbase.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/flbase.c 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,89 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/3/common/flbase.c-arc $ + * + * Rev 1.4 Oct 22 2007 11:34:52 einat.avidan + * update copyrights header + * + * Rev 1.3 Sep 11 2006 13:45:20 yaniv.iarovici + * Legal header added + * + * Rev 1.2 Aug 09 2006 16:52:48 Polina.Marimont + * initial for DOC Driver 1.0 + */ + +#include "flbase.h" + + +void toUNAL(FLByte FAR0 *unal, FLWord n) +{ + unal[0] = FL2BYTE(n); + unal[1] = FL2BYTE(n >> 8); +} + + +FLWord fromUNAL(FLByte const FAR0 *unal) +{ + return ((FLWord)unal[1] << 8) + unal[0]; +} + + +/* calling another routines looks nice, but it is slower */ + +void toUNALLONG(FLByte FAR0 *le, FLDword n) +{ + le[0] = FL2BYTE(n); + le[1] = FL2BYTE(n >> 8); + le[2] = FL2BYTE(n >> 16); + le[3] = FL2BYTE(n >> 24); +} + +FLDword fromUNALLONG(FLByte const FAR0 *le) +{ + return ((FLDword)le[3] << 24) + + ((FLDword)le[2] << 16) + + ((FLDword)le[1] << 8) + + le[0]; +} + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/flbase.h linux-2.6.30.4/drivers/block/tffs/flbase.h --- linux-2.6.30.4-orig/drivers/block/tffs/flbase.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/flbase.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,267 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ + +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/3/common/flbase.h-arc $ + * + * Rev 1.21 Oct 22 2007 11:34:52 einat.avidan + * update copyrights header + */ + +#ifndef FLBASE_H +#define FLBASE_H + +#include "flcustom.h" +#include "flsystem.h" +#include "flsystyp.h" +#include "flchkdef.h" +#include "flcommon.h" + +#ifndef MTD_STANDALONE +#include "flsysfun.h" +#endif /* MTD_STANDALONE */ + + /* Number of floors supported by the S/W + * + * Define Maximum Number of floors in a physical device + * + * The actual number of floors depends on the physical device placed + * on the socket. + */ + +#define FL_MAX_NO_OF_FLOORS 4 + + + +/* General purpose macros */ + +#define BYTE_ADD_FAR(x,y) ((FLByte FAR1 *)addToFarPointer((FLByte FAR1 *)x,y)) +#define WORD_ADD_FAR(x,y) ((FLWord FAR1 *)addToFarPointer((FLByte FAR1 *)x,y)) +#define DWORD_ADD_FAR(x,y) ((FLDword FAR1 *)addToFarPointer((FLByte FAR1 *)x,y)) +#define SBYTE_ADD_FAR(x,y) ((FLSByte FAR1 *)addToFarPointer((FLByte FAR1 *)x,y)) +#define SWORD_ADD_FAR(x,y) ((FLSWord FAR1 *)addToFarPointer((FLByte FAR1 *)x,y)) +#define SDWORD_ADD_FAR(x,y) ((FLSDword FAR1 *)addToFarPointer((FLByte FAR1 *)x,y)) + +/* Drive handle masks */ + +#define FL_GET_LOGICAL_PARTITION_FROM_HANDLE(ioreq) (FLByte)(((ioreq)->irHandle & 0xf00) >> 8) +#define FL_GET_DISK_HANDLE_FROM_S_P_LP(s,p, lp) ((s) | ((p) << 4) | ((FLHandle)(lp) << 8)) + +#define FL_SOCKET_AND_FLASH_PARTITION_BITS 0xFF + +#define FL_DO_NOT_UPDATE_MBR (1 << 14) /* used by formatFS only */ + +#define INVALID_VOLUME_NUMBER 0xff +#define TL_SIGNATURE 6 + +#define FL_SECTOR_MASK (FL_SECTOR_SIZE - 1) +#define BITS_PER_BITE 8 + + +/* General purpose macros adjusted according to the above customization files. */ + + +/* Call a procedure returning status and fail if it fails. This works only in */ +/* routines that return Status: */ +#define checkStatus(exp) { FLStatus fl__status = (exp);if (fl__status != flOK) return fl__status; } +#define updateStatus(cur__stat, exp) { FLStatus fl__status = (exp);if (cur__stat == flOK) cur__stat = fl__status; } + +#define TFFSMIN(a,b) (((a)>(b)) ? (b):(a)) +#define TFFSMAX(a,b) (((a)<(b)) ? (b):(a)) + +/***************************************************************************/ +/* Big \ Little endien architecture conversion macros. */ +/***************************************************************************/ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED +#define COPY2(to,arg) *((FLWord *)(&to)) = *((FLWord *)(&arg)) +#define COPY4(to,arg) *((FLDword *)(&to)) = *((FLDword *)(&arg)) +#else +#define COPY2(to, offs, arg) FL_REF_2(to, offs) = FL_REF_2(arg, offs) +#define COPY4(to, offs, arg) FL_REF_4(to, offs) = FL_REF_4(arg, offs) +#endif /* FL_NO_PACKED_STRUCTS_SUPPORTED */ + + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#define UNAL2(arg) fromUNAL(arg) +#define toUNAL2(to,arg) toUNAL(to,arg) + +#define UNAL4(arg) fromUNALLONG((FLByte const FAR0 *)(arg)) +#define toUNAL4(to,arg) toUNALLONG((FLByte FAR0 *)to,arg) + +/* for both LE and BE */ + +#define FL_GET_UNAL2(arg, offs) fromUNAL(((FLByte *)(arg)) + (offs)) +#define FL_SET_UNAL2(to, offs, arg) toUNAL(((FLByte *)(to)) + (offs), (arg)) +#define FL_GET_UNAL4(arg, offs) fromUNALLONG(((FLByte *)(arg)) + (offs)) +#define FL_SET_UNAL4(to, offs, arg) toUNALLONG(((FLByte *)(to)) + (offs), (arg)) + + +typedef LEulong LEmin; + +/*************************************************/ +/* Use routines instead of 'c' standard librarys */ +/*************************************************/ + +/**********************************************/ +/* Declare the TrueFFS environment variables */ +/**********************************************/ + +#ifdef FL_NO_USE_FUNC +/* The code bellow allows you to customize your own routine for multi bytes */ +/* transfers. Once FL_NO_USE_FUNC is defined, you can define the multi byte */ +/* macros to these routines, and code them yourself in flsystem.c */ +extern void FAR1 fl16bitDocReadNoShift (volatile FLByte FAR0 * win, FLWord offset, FLByte FAR1 * dest, FLWord count ); +extern void FAR1 fl16bitDocWriteNoShift ( volatile FLByte FAR0 * win , FLWord offset , FLByte FAR1 * src, FLWord count ); +#endif /* FL_NO_USE_FUNC */ + +#ifdef FL_ENVIRONMENT_VARS + +extern void flSetEnvVar(void); + +/**********************************************/ +/* Declare the TrueFFS environment variables */ +/**********************************************/ + +extern FLByte flDimageCfg; + +#ifndef MTD_STANDALONE + +extern FLByte flUseMultiDoc; +extern FLByte flMTLdefragMode; +extern FLByte flMaxUnitChain; +#ifdef FL_TFFS_OLD_ENV_VARS +extern FLByte flMarkDeleteOnFlash; +extern FLByte flPolicy[FL_SOCKETS][FL_MAX_TL_PARTITIONS]; +#endif /* FL_TFFS_OLD_ENV_VARS */ +extern FLWord flCacheSize[FL_SOCKETS][FL_MAX_TL_PARTITIONS]; +extern FLByte flSkipStaticFilesWearLeveling[FL_SOCKETS][FL_MAX_TL_PARTITIONS]; +extern FLByte flSuspendMode[FL_SOCKETS]; +extern FLDword flTFFSBDDebugMode[FL_SOCKETS][FL_MAX_TL_PARTITIONS]; +#ifdef FL_BD_AUTO_DPD_MODE +extern FLDword flBDAutoDPDMode[FL_SOCKETS]; +#endif /* FL_BD_AUTO_DPD_MODE */ + +#endif /* MTD_STANDALONE */ + +/* Policies definitions (FL_SET_POLICY) */ +#define FL_DEFAULT_POLICY 0 +#define FL_COMPLETE_ASAP 1 +#define FL_SECURED_DELETE 2 +/* Mtl policies definitions (FL_MTL_POLICY) */ +#define FL_MTL_DEFRAGMENT_ALL_DEVICES 0 +#define FL_MTL_DEFRAGMENT_SEQUANTIAL 1 +/* Suspend mode other then FL_OFF */ +#define FL_SUSPEND_WRITE 1 +#define FL_SUSPEND_IO 3 +#define FL_IGNORE_WRITE 4 +#define FL_IGNORE_ERASE 8 +#define FL_PREVENT_IO (FL_IGNORE_ERASE | FL_IGNORE_WRITE | FL_SUSPEND_IO | FL_SUSPEND_WRITE) +/* Runtime replacement for compilation flags */ +#define FL_DIMAGE 0x01 +#define FL_PUTIMAGE 0x02 +#define FL_PUTIMAGE_PARALLEL 0x04 +#define FL_DIMAGE_ALL (FL_DIMAGE | FL_PUTIMAGE | FL_PUTIMAGE_PARALLEL) +/* Cache full media */ +#define FL_MAX_ALLOWED_TL_CACHE_SIZE 0xFFF + + +#ifndef FL_DEFAULT_POLICY_MODE +#define FL_DEFAULT_POLICY_MODE(socket,partition) FL_OFF +#endif /* FL_DEFAULT_POLICY_MODE */ +#ifndef FL_DEFAULT_BD_DPD_MODE +#define FL_DEFAULT_BD_DPD_MODE(socket) FL_OFF +#endif /* FL_DEFAULT_BD_DPD_MODE */ +#ifndef FL_DEFAULT_BD_SUSPEND_MODE +#define FL_DEFAULT_BD_SUSPEND_MODE(socket) FL_OFF +#endif /* FL_DEFAULT_BD_SUSPEND_MODE */ +#ifndef FL_DEFAULT_BD_DEBUG_MODE +#define FL_DEFAULT_BD_DEBUG_MODE(socket,partition) FL_OFF +#endif /* FL_DEFAULT_BD_DEBUG_MODE */ +/* Either per partition or for all (backward compatible) */ +#ifndef FL_DEFAULT_CACHE_SIZE_FOR_MINIMAL_CACHE +#define FL_DEFAULT_CACHE_SIZE_FOR_MINIMAL_CACHE 0x40 +#endif /* FL_DEFAULT_CACHE_SIZE_FOR_MINIMAL_CACHE */ +#ifndef FL_DEFAULT_TL_CACHE_SIZE +#define FL_DEFAULT_TL_CACHE_SIZE(socket,partition) FL_DEFAULT_CACHE_SIZE_FOR_MINIMAL_CACHE +#endif /* FL_DEFAULT_TL_CACHE_SIZE */ +#ifndef FL_DEFAULT_WEARLEVELING_MODE +#define FL_DEFAULT_WEARLEVELING_MODE(socket,partition) FL_OFF +#endif /* FL_DEFAULT_WEARLEVELING_MODE */ +#ifndef FL_DEFAULT_VERIFY_WRITE_MODE +#define FL_DEFAULT_VERIFY_WRITE_MODE(socket,partition) FL_OFF +#endif /* FL_DEFAULT_VERIFY_WRITE_MODE */ +#ifndef FL_DEFAULT_TOOLS_MODE +#define FL_DEFAULT_TOOLS_MODE FL_OFF +#endif /* FL_DEFAULT_TOOLS_MODE */ + +#endif /* FL_ENVIRONMENT_VARS */ + +/* Set default to bus configuration (unless specified differently in flsystem.h */ +#ifndef FL_DEFAULT_BUS_CONFIGURATION +#if (!defined(CHARSIZE) || (CHARSIZE != 16)) +#define FL_DEFAULT_BUS_CONFIGURATION (FL_NO_ADDR_SHIFT | FL_BUS_HAS_8BIT_ACCESS | \ + FL_BUS_HAS_16BIT_ACCESS | FL_BUS_HAS_32BIT_ACCESS) +#else +#define FL_DEFAULT_BUS_CONFIGURATION (FL_NO_ADDR_SHIFT | FL_BUS_HAS_16BIT_ACCESS) +#endif /* CHARSIZE */ +#endif /* FL_DEFAULT_BUS_CONFIGURATION */ + +#ifndef FL_DEFAULT_BUS_MODE +#define FL_DEFAULT_BUS_MODE(socket) FL_DEFAULT_BUS_CONFIGURATION +#endif /* FL_DEFAULT_BUS_MODE */ + + +#endif /* FLBASE_H */ + + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/flbuffer.h linux-2.6.30.4/drivers/block/tffs/flbuffer.h --- linux-2.6.30.4-orig/drivers/block/tffs/flbuffer.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/flbuffer.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,76 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ + +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/3/common/flbuffer.h-arc $ + * + * Rev 1.7 Oct 22 2007 11:34:52 einat.avidan + * update copyrights header + * + * Rev 1.6 Sep 11 2006 13:45:20 yaniv.iarovici + * Legal header added + * + * Rev 1.5 Sep 05 2006 17:21:34 rafib + * Fix slow mount problem in H1 512 hynix + * + * Rev 1.4 Aug 09 2006 16:52:50 Polina.Marimont + * initial for DOC Driver 1.0 + */ + +#ifndef FLBUFFER_H +#define FLBUFFER_H + +#include "flbase.h" + +#define READ_BACK_BUFFER_SIZE 1024 /* Size of read back buffer + Must be multiplication of 512 */ +typedef struct { + FLByte flData[FL_SECTOR_SIZE]; /* sector buffer */ + FLByte flData2[FL_SECTOR_SIZE]; /* sector buffer */ + SectorNo sectorNo; /* current sector in buffer */ + void *owner; /* owner of buffer */ + FLBoolean dirty; /* sector in buffer was changed */ + FLBoolean checkPoint; /* sector in buffer must be flushed */ +} FLBuffer; + +#endif diff -urN linux-2.6.30.4-orig/drivers/block/tffs/flchkdef.h linux-2.6.30.4/drivers/block/tffs/flchkdef.h --- linux-2.6.30.4-orig/drivers/block/tffs/flchkdef.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/flchkdef.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,1550 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ + +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/3/common/flchkdef.h-arc $ + * + * Rev 1.103 Mar 17 2008 13:22:42 einat.avidan + * increase EQA version + * + * Rev 1.102 Mar 09 2008 17:01:38 Yuli.Izrailov + * Set DOCH_CHIP_ID_TRIALS_FOR_SLAVE to DOCH_MOUNT_WAIT + * Changed EQA and RC numbers + * + * Rev 1.101 Feb 03 2008 14:28:52 Yuli.Izrailov + * HW_OTP, HW_PROTECTION, FL_EXTENDED_DISK_INFO, NO_IPL_CODE flags moved here from flcustom.h under FL_CODE_REDUCTION compilation flag. + * + * Rev 1.99 Dec 26 2007 11:58:02 einat.avidan + * update version + * + * Rev 1.98 Dec 04 2007 17:38:06 einat.avidan + * Define delay for accessing same register twice + * Inc version + * + * Rev 1.97 Dec 03 2007 18:04:02 einat.avidan + * update EQA number + * + * Rev 1.96 Nov 07 2007 19:20:42 einat.avidan + * add defenition for FLTXT_VAR + * update EQA number + * + * Rev 1.95 Nov 05 2007 17:53:14 einat.avidan + * EQA5 + * + * Rev 1.94 Oct 30 2007 17:06:30 einat.avidan + * update version number + * Exported DMA flags receive the values of internal flags + * + * Rev 1.93 Oct 23 2007 12:27:54 einat.avidan + * optimization: delay after setting head register only + * when switching floors + * + * Rev 1.92 Oct 22 2007 11:34:52 einat.avidan + * update copyrights header + * + * Rev 1.91 Oct 21 2007 16:59:48 einat.avidan + * fix compilation warnings + * + * Rev 1.90 Oct 21 2007 10:44:06 Einat.Avidan + * add definition for delay after each trial of reading chip ID from SLAVE + * add definition for number of trials of reading chip ID + * default definition of DOCH_SET_WINDOW_OFFSET should return value + * update version number + * + * Rev 1.89 Oct 11 2007 19:04:00 Einat.Avidan + * update version number + * add definition for delay after device switch + * + * + * Rev 1.88 Jul 01 2007 13:47:28 einat.avidan + * bug fix: SCR 2964 compilation flag FL_VERIFY_WRITE should exclude \ include code for write verification + * + * Rev 1.87 Jun 20 2007 12:23:36 einat.avidan + * update verion DD 1.1 EQA1 (internal R&D) + * + * Rev 1.86 Mar 22 2007 16:57:54 einat.avidan + * set version 1.1 EQA0 + * + * Rev 1.85 Mar 11 2007 16:39:46 einat.avidan + * bug fix: working on x86 requires read buffer not to be paged out + * replace the former solution (access to the begining and the end of the buffer under NO_INIT_MMU_PAGES compilation flag) + * with full solution: usage of a buffer that is locked on RAM + * + * Rev 1.84 Feb 28 2007 10:50:46 einat.avidan + * bug fix: scr 2831 removed unnecessary definitions: FL_MTDS, FL_TLS, MTD_READ_BBT. + * + * Rev 1.83 Feb 28 2007 10:33:20 einat.avidan + * inc EQA version + * bug fix: “;” at the end of macros definition in flcheckdef may cause compilation errors + * + * Rev 1.82 Feb 15 2007 17:52:18 Einat.Avidan + * New compilation flags: + * DOCH_READ_STATUS_ASYNC_IN_BURST + * DOCH_USE_BURST_MODE_READ_ONLY_IN_DMA + * + * Rev 1.81 Jan 01 2007 15:35:12 einat.avidan + * updated to EQA21 + * bug fix: scr2811, boot shceme failed when only one device exists and the reset/warm reset pins of the MDOC are NOT connected to the CPU reset. + * the fix - changed default number of ATA_MAX_NUM_OF_DEVICES to 1. + * + * Rev 1.78.2.16.1.3 Dec 10 2006 17:02:56 Yaniv.Iarovici + * Update EQA 20 + * + * Rev 1.78.2.16.1.2 Dec 05 2006 14:59:14 Yaniv.Iarovici + * Change EQA to 19. + * + * Rev 1.78.2.16.1.1 Dec 04 2006 12:44:48 Yaniv.Iarovici + * Change EQA to 18. + * + * Rev 1.78.2.16.1.0 Dec 03 2006 13:43:14 Yaniv.Iarovici + * Header update + * + * Rev 1.78.2.17 Dec 03 2006 13:32:26 Yaniv.Iarovici + * 1. Change EQA to 17. + * 2. Removed DOCH_FLOORS. + * Encapsulate auto wipe-sector operation for Dev1 under '#ifndef DOCH_NO_AUTO_WIPE_SECTORS_DEV1' + * + * Rev 1.78.2.16 Nov 30 2006 10:24:02 Yaniv.Iarovici + * 1. Change EQA to 16. + * 2. Add default customization for DOCH_WAIT_B4_DEV1_ID. + * + * Rev 1.78.2.15 Nov 21 2006 14:27:06 Yaniv.Iarovici + * Update EQA to 15. + * + * Rev 1.78.2.14 Nov 13 2006 15:14:04 Yaniv.Iarovici + * Change EQA to 14. + * + * Rev 1.78.2.13 Nov 12 2006 09:47:42 Yaniv.Iarovici + * 1. Changed version to EQA12 RC2. + * 2. Added default values for + * - FL_IPL_DELAY_CELL_CONFIG_READ + * - FL_IPL_DELAY_CELL_CONFIG_WRITE + * + * Rev 1.78.2.12 Nov 01 2006 08:56:04 Yaniv.Iarovici + * Change version to EQA12. + * + * Rev 1.78.2.11 Oct 31 2006 12:23:52 yaniv.iarovici + * Change version to EQA11. + * + * Rev 1.78.2.10 Oct 30 2006 15:50:32 yaniv.iarovici + * Change version to EQA10. + * + * Rev 1.78.2.9 Oct 29 2006 14:24:12 Yaniv.Iarovici + * Change version to EQA9. + * + * Rev 1.78.2.8 Oct 29 2006 10:59:50 Yaniv.Iarovici + * Change version to EQA8. + * + * Rev 1.78.2.7 Oct 25 2006 09:10:34 Yaniv.Iarovici + * Change version to EQA7 + * + * Rev 1.78.2.6 Oct 23 2006 11:29:20 yaniv.iarovici + * Change EQA to 6 + * + * Rev 1.78.2.5 Oct 09 2006 14:05:24 yaniv.iarovici + * Removed legacy devices related code and definitions + * + * Rev 1.78.2.4 Oct 05 2006 11:48:12 yaniv.iarovici + * Change version to 'DOC Driver 1.0, EQA4, RC1' + * + * Rev 1.78.2.3 Sep 13 2006 10:44:22 yaniv.iarovici + * Update version to EQA3 Alpha2 + * + * Rev 1.78.1.6 Sep 11 2006 13:45:20 yaniv.iarovici + * Legal header added + * + * Rev 1.78.1.5 Sep 10 2006 10:04:00 Yaniv.Iarovici + * Update version number - DOC Driver 1.0 EQA1 Alpha2. + * + * Rev 1.78.1.4 Sep 03 2006 14:44:50 Yaniv.Iarovici + * 1. Define flReadEvenNumberOfBytes() instead of flRead512Bytes() to support DRQ>1 + * 2. Define flWriteEvenNumberOfBytes() instead of flWrite512Bytes() to support DRQ>1 + * + * Rev 1.78.1.3 Aug 22 2006 13:24:40 Yaniv.Iarovici + * Change FL_MAX_TL_PARTITIONS default to '14' + * + * Rev 1.78.1.2 Aug 16 2006 08:46:36 Yaniv.Iarovici + * 1) Change 7.0.0.0 to 1.0.0.0 + * 2) Change TrueFFSVersion value to "1020" + * 3) If FL_DOC_ADDRESS is NOT defined and FL_LOW_DOC_ADDRESS defined, set '#define FL_DOC_ADDRESS FL_LOW_DOC_ADDRESS'. + * + * Rev 1.78.1.0 Aug 08 2006 15:55:30 Polina.Marimont + * DOC Driver 1.0 initial + */ + +/************************/ +/* TrueFFS source files */ +/* -------------------- */ +/************************/ + +/***************************************************************************** +* File Header * +* ----------- * +* Name : flchkdef.h * +* * +* Description : Sanity check for flcustom.h files. * +* * +*****************************************************************************/ + +#ifndef _FL_CHK_DEFS_H_ +#define _FL_CHK_DEFS_H_ + +#include "flcustom.h" +#include "flsystem.h" + +#define FL_MIGRATION_VERSION + +#define FL_NEW_MAPSECTOR + +#ifndef MTD_STANDALONE + +/* TrueFFS version + * + * Number written on the flash by INFTL format specifying the TrueFFS version + * The media was formated with. the number bellow specifies version + * 1.1.0.0 + */ + +#define TrueFFSVersion "1100" + +/* Tracking number for TrueFFS configuration management + * + * Number for configuration management of special purpose versions + */ + +#define TrueFFS_EQA_Version 12 +#define TrueFFS_RC_Version 3 +#define TrueFFS_PATCH_Version 0 +#define TrueFFS_Alpha_Version 0 +#define TrueFFS_Beta_Version 0 + + +/* Programmer type version + * + * This string is placed in the media header indicating the programmer + * Name and version used to format the media + */ + +#ifndef FL_PROGRAMMER_NAME +#define FL_PROGRAMMER_NAME "CORE" +#endif /* FL_PROGRAMMER_NAME */ + +#ifndef FL_PROGRAMMER_VERSION +#define FL_PROGRAMMER_VERSION "0000" +#endif /* FL_PROGRAMMER_VERSION */ + +/********************************************************************/ +/* Device base address (Use previous versions definition if exits */ +/* and FL_DOC_ADDRESS does not exist. */ +/********************************************************************/ +#if !defined(FL_DOC_ADDRESS) && defined(FL_LOW_DOC_ADDRESS) +#define FL_DOC_ADDRESS FL_LOW_DOC_ADDRESS +#endif + +/*******************************************/ +/* Validity check and overlapping defines */ +/*******************************************/ + +#if !defined(FL_READ_ONLY) && !defined(FS_READ_ONLY) && defined(READ_ONLY) +#define FL_READ_ONLY +#define FS_READ_ONLY +#endif + +/* The format option needs some internal defintions */ +#if !defined(FL_FORMAT_VOLUME) && defined(FORMAT_VOLUME) +#define FL_FORMAT_VOLUME +#endif + +#if (defined(FL_FORMAT_VOLUME) && defined(FL_READ_ONLY)) +#error "You can not define FL_READ_ONLY and FL_FORMAT_VOLUME at the same time" +#endif /* (defined(FL_FORMAT_VOLUME) && defined(FL_READ_ONLY)) */ + +#if (defined(FS_FORMAT_VOLUME) && defined(FS_READ_ONLY)) +#error "You can not define FS_READ_ONLY and FS_FORMAT_VOLUME at the same time" +#endif /* (defined(FS_FORMAT_VOLUME) && defined(FS_READ_ONLY)) */ + +#if (defined(FS_CREATE_LOGICAL_PARTITIONS) && defined(FS_READ_ONLY)) +#error "You can not define FS_READ_ONLY and FS_CREATE_LOGICAL_PARTITIONS" +#endif + +/* In case FL_READ_ONLY is defined FS_READ_ONLY needs to be defined as well */ +#ifdef FL_READ_ONLY +#ifndef FS_READ_ONLY +#define FS_RED_ONLY +#endif /* FS_READ_ONLY */ +#endif /* FL_READ_ONLY */ + +/* Validity check for system files MACROES */ +#ifndef FL_FOPEN +#define FL_FOPEN +#endif /* FL_FOPEN */ +#ifndef FL_FCLOSE +#define FL_FCLOSE +#endif /* FL_FCLOSE */ +#ifndef FL_FPRINTF +#define FL_FPRINTF +#endif /* FL_FPRINTF */ + + +/* Number of file system - logical partitions + * + * Defines Maximum Number of logical partitons on a BDTL partition + * + * The actual number of partitions depends on the format placed on each device. + */ + +#ifndef FS_MAX_LOGICAL_PARTITIONS +#define FS_MAX_LOGICAL_PARTITIONS 4 /* per TL partition. There is no hard limit */ +#endif /* FS_MAX_LOGICAL_PARTITIONS */ + + +/* Validity check of FL_VOLUMES and FL_SOCKETS parameters. */ + +#if !defined(FL_VOLUMES) && defined(VOLUMES) +#define FL_VOLUMES VOLUMES +#endif + +#if !defined(FS_VOLUMES) && defined(FL_VOLUMES) +#define FS_VOLUMES FL_VOLUMES +#endif + +#if !defined(FL_SOCKETS) && defined(SOCKETS) +#define FL_SOCKETS SOCKETS +#endif + +#if !defined(FS_SOCKETS) && defined(FL_SOCKETS) +#define FS_SOCKETS FL_SOCKETS +#endif + + +#if !defined(FL_VOLUMES) && defined(FL_SOCKETS) +#define FL_VOLUMES FL_SOCKETS +#endif /* SOCKETS && ! VOLUMES */ + +#if !defined(FS_VOLUMES) && defined(FS_SOCKETS) +#define FS_VOLUMES FS_SOCKETS +#endif /* SOCKETS && ! VOLUMES */ + +#if !defined(FL_SOCKETS) && defined(FL_VOLUMES) +#define FL_SOCKETS FL_VOLUMES +#endif /* ! SOCKETS && VOLUMES */ + +#if !defined(FS_SOCKETS) && defined(FS_VOLUMES) +#define FS_SOCKETS FS_VOLUMES +#endif /* ! SOCKETS && VOLUMES */ + +#if (FL_SOCKETS > FL_VOLUMES) || (FS_SOCKETS > FS_VOLUMES) +#error "SOCKETS should not be bigger then VOLUMES" +#endif /* SOCKETS > VOLUMES */ + +/* The POLLING_INTERVAL definition is not really relevant to DiskOnChip + * Starting from TrueFFS 6.1 it was removed from flcustom.h, but TrueFFS + * still support this functionality. + */ +#ifndef POLLING_INTERVAL +#define POLLING_INTERVAL 0 +#endif /* POLLING_INTERVAL */ + +/* TrueFFS 5.2 used the FL_QUICK_MOUNT_INFO_EXIST defintion. TrueFFS 6.1 + * uses simple FL_ON and FL_OFF instead. + */ + +#define FL_QUICK_MOUNT_INFO_EXIST FL_ON + +/* Starting from TrueFFS 6.1 this flag does not reduce code and therfore was + * added as a default. + * + */ + +#define FL_LOW_LEVEL + +/* Some S/W modules like boot SDK do not need the read bad blocks tables routine. + * However for TrueFFS these definition is vital + */ + +/* 12-bit FAT support + * + * Comment the following line if you do not need support for DOS media with + * 12-bit FAT (typically media of 8 MBytes or less). + */ + +#define FS_FAT_12BIT + + + +#ifndef FL_SOCKETS +#define FL_SOCKETS 1 /* The only available number */ +#endif +#define FIXED_MEDIA +#define DO_NOT_YIELD_CPU + +#endif /* MTD_STANDALONE */ + + +/* Enable H/W protection of the device. + * + * Enable H/W One Time Programming capability including the unique ID feature. + * + * Compile the extended Disk information routine. + * TrueFFS 6.0 and up provide an extended information routine for internal + * SanDisk utilities named flGetExtendedDiskInfo(). + */ + +#ifndef FL_CODE_REDUCTION + #ifndef HW_PROTECTION + #define HW_PROTECTION + #endif /* HW_PROTECTION */ + + #ifndef HW_OTP + #define HW_OTP + #endif /* HW_OTP */ + + #ifndef FL_EXTENDED_DISK_INFO + #define FL_EXTENDED_DISK_INFO + #endif /* FL_EXTENDED_DISK_INFO */ +#else /* FL_CODE_REDUCTION */ + #ifndef NO_IPL_CODE + #define NO_IPL_CODE + #endif /* NO_IPL_CODE */ +#endif /* FL_CODE_REDUCTION */ + + +/* Number of translation layer partitions + * + * Defines Maximum Number of Translation layer partitions on a physical device + * + * The actual number of partitions depends on the format placed on each device. + */ + +#ifndef FL_MAX_TL_PARTITIONS +#define FL_MAX_TL_PARTITIONS 14 +#endif /* FL_MAX_TL_PARTITIONS */ + +/* The Maximum number of partitions is limited to 8 due to SAFTL buffers */ + +#if (FL_MAX_TL_PARTITIONS > 14) +#error "Can not define more then 14 partitions\r\n" +#endif /* (FL_MAX_TL_PARTITIONS > 8) */ + + +/* Max Number of binary partitions */ +#ifndef MAX_BINARY_PARTITIONS_PER_DRIVE +#define MAX_BINARY_PARTITIONS_PER_DRIVE 3 +#endif /* MAX_BINARY_PARTITIONS_PER_DRIVE */ + +/* There can not be more binary partition, then total supported partitions */ +#if (MAX_BINARY_PARTITIONS_PER_DRIVE >= FL_MAX_TL_PARTITIONS) +#error "MAX_BINARY_PARTITIONS_PER_DRIVE must be smaller then FL_MAX_TL_PARTITIONS\r\n" +#endif /* (MAX_BINARY_PARTITIONS_PER_DRIVE >= FL_MAX_TL_PARTITIONS) */ + +/* Default file system TL partitions */ +#if !defined(FS_MAX_TL_PARTITIONS) && defined(FL_MAX_TL_PARTITIONS) +#define FS_MAX_TL_PARTITIONS FL_MAX_TL_PARTITIONS +#endif + + +/* Make sure that the CHARSIZE is well defined */ +#ifndef CHARSIZE +#define CHARSIZE 8 /*The default char size is 8*/ +#endif + +/* Make sure flPack and flspread are well defined */ +#if (CHARSIZE == 8) +#ifndef flspread +#define flspread(source,length) +#endif /* flspread */ + +#ifndef flpack +#define flpack(source,length) +#endif /* flpack */ +#endif /* (CHARSIZE == 8) */ + +/* Make sure FL2BYTE is well defined */ +#ifndef FL2BYTE +#if (CHARSIZE == 8) +#define FL2BYTE(var) ((FLByte)(var)) +#else +#define FL2BYTE(var) ((FLByte)((var) & 0x00FF)) +#endif /* (CHARSIZE == 8) */ +#endif /* FL2BYTE */ + + +#ifndef FL_PACKED_STRUCTURES_BEFORE +#define FL_PACKED_STRUCTURES_BEFORE +#endif /* FL_PACKED_STRUCTURES_BEFORE */ + +#ifndef FL_PACKED_STRUCTURES_AFTER +#ifdef FL_PACKED_STRUCTURES +#define FL_PACKED_STRUCTURES_AFTER FL_PACKED_STRUCTURES +#else +#define FL_PACKED_STRUCTURES_AFTER +#endif /* FL_PACKED_STRUCTURES */ +#endif /* FL_PACKED_STRUCTURES_AFTER */ + +/* Starting from TrueFFS version 6.x the ASSUMED_NFTL_UNIT_SIZE was changed to + * FL_ASSUMED_MIN_UNIT_SIZE. + */ + +#ifndef FL_ASSUMED_MIN_UNIT_SIZE +#define FL_ASSUMED_MIN_UNIT_SIZE ASSUMED_NFTL_UNIT_SIZE +#endif /* FL_ASSUMED_MIN_UNIT_SIZE */ + +/* Starting from TrueFFS version 6.x the MAX_VOLUME_MBYTES was changed to + * FL_ASSUMED_MAX_VOLUME_MBYTES. + */ + +#ifndef FL_ASSUMED_MAX_VOLUME_MBYTES +#ifdef MAX_VOLUME_MBYTES +#define FL_ASSUMED_MAX_VOLUME_MBYTES MAX_VOLUME_MBYTES +#else + +/* TrueFFS sets the sector size according to this definitions. As a result customers + that do not customize this definition will be limited to a very small media (32MB) + without even knowing it. + */ + +#define FL_ASSUMED_MAX_VOLUME_MBYTES 64 +#endif /* MAX_VOLUME_MBYTES */ +#endif /* FL_ASSUMED_MAX_VOLUME_MBYTES */ + +/* When using static allocation , SAFTL may requires the number of sectors + * in a logical unit. This value can normally be deduced from the unit size. + * However if you need to support several DiskOnChip devices with different + * unit sizes, you may need to define the smallest unit size, while defining + * the largest number of logical sectors in a logical unit + */ + +#ifndef FL_ASSUMED_MAX_SECTORS_PER_UNIT +#define FL_ASSUMED_MAX_SECTORS_PER_UNIT (FL_ASSUMED_MIN_UNIT_SIZE>>FL_SECTOR_SIZE_BITS) +#endif /* FL_ASSUMED_MAX_SECTORS_PER_UNIT */ + +/* Validity check for FL_LOW_LEVEL compilation flag. + * + * Starting from TrueFFS 5.1 the LOW_LEVEL was changed to FL_LOW_LEVEL + * The reason was that it clashed with Windows NT LOW_LEVEL macro. + */ + +#ifndef FL_LOW_LEVEL +#ifdef LOW_LEVEL +#define FL_LOW_LEVEL +#endif /* LOW_LEVEL */ +#endif /* FL_LOW_LEVEL */ + + +#if !defined(FL_ABS_READ_WRITE) && !defined(FS_ABS_READ_WRITE) && defined(ABS_READ_WRITE) +#define FL_ABS_READ_WRITE +#define FS_ABS_READ_WRITE +#endif + +/* Validity check for FL_SYS_FUNC_RELEASE + * + * Starting from TrueFFS 6.0 the flExit routine calls this macro in + * order to inform the OS/FS that it is about to leave. + */ + +#ifndef FL_SYS_FUNC_RELEASE +#define FL_SYS_FUNC_RELEASE +#endif /* FL_SYS_FUNC_RELEASE */ + +#if !defined(FL_EXIT) && !defined(FS_EXIT) && defined(EXIT) +#define FL_EXIT +#define FS_EXIT +#endif + +/* Validity check for FL_LOWER_PRIORITY_THREAD and FL_RAISE_PRIORITY_THREAD + * + * Starting from TrueFFS 6.0-6.2.2 the MTD waitForReady routine calls the + * FL_LowerPriorityThread and FL_RaisePriorityThread macros allowing the OS + * to lower the driver's priority during the long wait. + * + * After 6.2.2 the name of the macros was changed to all upper case. + */ + +#ifndef FL_LOWER_PRIORITY_THREAD +#ifdef FL_LowerPriorityThread +/*** Add support for older flsystem that use FL_Raise/LowerPriorityThread macros ***/ +#define FL_LOWER_PRIORITY_THREAD FL_LowerPriorityThread +#else +#define FL_LOWER_PRIORITY_THREAD(myFlash) +#endif /* FL_LowerPriorityThread */ +#endif /* FL_LOWER_PRIORITY_THREAD */ + +#ifndef FL_RAISE_PRIORITY_THREAD +#ifdef FL_RaisePriorityThread +/*** Add support for older flsystem that use FL_Raise/LowerPriorityThread macros ***/ +#define FL_RAISE_PRIORITY_THREAD FL_RaisePriorityThread +#else +#define FL_RAISE_PRIORITY_THREAD(myFlash) +#endif /* FL_RaisePriorityThread */ +#endif /* FL_RAISE_PRIORITY_THREAD */ + +#ifndef FL_LowerPriorityThread +#define FL_LowerPriorityThread(myFlash) +#endif /* FL_LowerPriorityThread */ + +#ifndef FL_RaisePriorityThread +#define FL_RaisePriorityThread(myFlash) +#endif /* FL_RaisePriorityThread */ + + +/* Validity check for FL_TFFS_SLEEP + * + * Note that this routine used to be called flsleep, but it's name was + * greater resolution was required. + */ + +#ifndef FL_TFFS_SLEEP +#define FL_TFFS_SLEEP(flash,microseconds) +#endif /* FL_TFFS_SLEEP */ + + +/* Validity check for FL_READ_ONLY + * + * When Block device does not support write operations, also file system + * cannot write. Therefore, if BD read only is set - also FS read only must be set. + */ +#ifdef FL_READ_ONLY +#define FS_READ_ONLY +#endif /*FS_READ_ONLY*/ + +/* Validity check for FL_MALLOC and FL_FREE macros + * + * Starting from TrueFFS 5.0 the FREE and MALLOC macroes were + * changed to FL_MALLOC and FL_FREE in order to avoid name clashes. + * In order to keep backwards compatibility with previous flsystem.h + * files the following new defintions checks were added. + * if your system uses the FREE and MALLOC defintion simply comment + * them out and customized the FL_MALLOC and FL_FREE macroes in your + * flsystem.h file. + */ + +#if (defined(MALLOC) && !defined(FL_MALLOC)) +#define FL_MALLOC MALLOC +#endif /* MALLOC && ! FL_MALLOC */ +#if (defined(FREE) && !defined(FL_FREE)) +#define FL_FREE FREE +#endif /* FREE && ! FL_FREE */ + + +/* Validity check for "subFromFarPointer" and "distanceBetweenFarPointers" + * + * Starting from TrueFFS 6.3.0 2 new memory manipulation macro's were + * introduced for none flat memory architecture. They should be used when + * memory pointers are being subtracted or a difference between 2 pointers + * is needed + */ + +#ifndef subFromFarPointer +#define subFromFarPointer(base,increment) \ + addToFarPointer(base,(-(FLSDword)(increment))) +#endif /* subFromFarPointer */ + +#ifndef distanceBetweenFarPointers +#define distanceBetweenFarPointers(ptr1, ptr2) \ + (((FLDword)(ptr1)) - ((FLDword)(ptr2))) +#endif /* distanceBetweenFarPointers */ + + +/* Validity check for FL_FAR_MALLOC and FL_FAR_FREE + * + * Due to the BIOS driver memory limitations a dedicated routine + * is used for allocating the large ram arrays. + */ + +#if (defined(FL_MALLOC) && !defined(FL_FAR_MALLOC)) +#define FL_FAR_MALLOC FL_MALLOC +#endif /* FL_MALLOC && ! FL_FAR_MALLOC */ + +#if (defined(FL_FREE) && !defined(FL_FAR_FREE)) +#define FL_FAR_FREE FL_FREE +#endif /* FL_MALLOC && ! FL_FAR_MALLOC */ + + +#ifndef FL_MALLOC_DMA_BUFFER +#define FL_MALLOC_DMA_BUFFER FL_FAR_MALLOC +#endif + +#ifndef FL_FREE_DMA_BUFFER +#define FL_FREE_DMA_BUFFER FL_FAR_FREE +#endif + + +/* Validity check for debug printing + * + * Starting from TrueFFS 6.0 there are 6 types of debug print + * In case they were not customized in flsystem.h they are defined here + * as NULL. + */ + +#ifndef DBG_PRINT_FLOW +#define DBG_PRINT_FLOW(zone,str) /* if (zone & (ACTIVE_DEBUG_ZONE)) printf (str) */ +#endif +#ifndef DBG_PRINT_ERR +#define DBG_PRINT_ERR(zone,str) /* if (zone & (ACTIVE_DEBUG_ZONE)) printf (str) */ +#endif +#ifndef DBG_PRINT_WRN +#define DBG_PRINT_WRN(zone,str) /* if (zone & (ACTIVE_DEBUG_ZONE)) printf (str) */ +#endif +#ifndef DBG_PRINT_FLOW_PRM +#define DBG_PRINT_FLOW_PRM(zone,str) /* if (zone & (ACTIVE_DEBUG_ZONE)) printf str */ +#endif +#ifndef DBG_PRINT_ERR_PRM +#define DBG_PRINT_ERR_PRM(zone,str) /* if (zone & (ACTIVE_DEBUG_ZONE)) printf str */ +#endif +#ifndef DBG_PRINT_WRN_PRM +#define DBG_PRINT_WRN_PRM(zone,str) /* if (zone & (ACTIVE_DEBUG_ZONE)) printf str */ +#endif + +#ifndef DBG_PRINT_ATA + #define DBG_PRINT_ATA DBG_PRINT_ERR_PRM +#endif /*DBG_PRINT_ATA*/ + + +#ifndef DFORMAT_PRINT +#define DFORMAT_PRINT(a) DBG_PRINT_WRN_PRM(FLZONE_FORMAT,a) +#endif +#ifndef DEBUG_PRINT +#define DEBUG_PRINT(a) DBG_PRINT_WRN(FLZONE_FULL,a) +#endif + + + +/* For backwards compatibility we make sure tffsxxx is defined as flxxx + * + * Versions prior to 6.1 (when ENVIRONMENT_VARS was defined) the user was + * required to customize 2 sets of DiskOnChip memory access routines. + * (flxxx and flmemxxx). One set was for fast memory access and one + * implemented a simple for loop for maximum platform portability. Newer + * versions automatically implement the simple for loop allowing easier + * customization. The new customization model allows the user to customize + * only the tffsxxx routines regardless of the compilation flag + */ + +#if !defined(FL_ENVIRONMENT_VARS) && defined(ENVIRONMENT_VARS) +#define FL_ENVIRONMENT_VARS +#endif + +#ifdef FL_ENVIRONMENT_VARS +#ifndef tffscpy +#define tffscpy flcpy +#endif /* tffscpy */ +#ifndef tffscmp +#define tffscmp flcmp +#endif /* tffscmp */ +#ifndef tffsset +#define tffsset flset +#endif /* tffsset */ +#endif /* FL_ENVIRONMENT_VARS */ + +/* Macro for converting text to string */ +#ifndef FLTXT +#define FLTXT +#endif /* FLTXT */ + +#ifndef FLTXT_VAR +#define FLTXT_VAR +#endif /* FLTXT */ + +/*****************************/ +/* M-Systems forced defaults */ +/*****************************/ + +/* define IO memory access macros - must be defined in flsystem.h */ +#ifndef FLWRITE_IO_BYTE +#define FLWRITE_IO_BYTE(val,address) *((volatile FLByte FAR0*)(address))=(FLByte)(val) +#endif +#ifndef FLWRITE_IO_WORD +#define FLWRITE_IO_WORD(val,address) *((volatile FLWord FAR0*)(address))=(FLWord)(val) +#endif +#ifndef FLWRITE_IO_DWORD +#define FLWRITE_IO_DWORD(val,address) *((volatile FLDword FAR0*)(address))=(FLDword)(val) +#endif +#ifndef TFFSCPY_FROM_IO_8_BITS +#ifdef TFFSCPY_FROM_IO +#define TFFSCPY_FROM_IO_8_BITS TFFSCPY_FROM_IO +#else +#define TFFSCPY_FROM_IO_8_BITS(dest,src,count) tffscpy(dest,(void FAR0*)(src),count) +#endif +#endif /* TFFSCPY_FROM_IO_8_BITS */ + +#ifndef TFFSCPY_FROM_IO_16_BITS +#ifdef TFFSCPY_FROM_IO +#define TFFSCPY_FROM_IO_16_BITS TFFSCPY_FROM_IO +#else +#define TFFSCPY_FROM_IO_16_BITS(dest,src,count) tffscpy(dest,(void FAR0*)(src),count) +#endif +#endif /* TFFSCPY_FROM_IO_16_BITS */ + +#ifndef FLREAD_IO_BYTE +#define FLREAD_IO_BYTE(address) (*((volatile FLByte FAR0*)(address))) +#endif +#ifndef FLREAD_IO_WORD +#define FLREAD_IO_WORD(address) (*((volatile FLWord FAR0*)(address))) +#endif +#ifndef FLREAD_IO_DWORD +#define FLREAD_IO_DWORD(address) (*((volatile FLDword FAR0*)(address))) +#endif + +#ifndef TFFSCPY_TO_IO_8_BITS +#ifdef TFFSCPY_TO_IO +#define TFFSCPY_TO_IO_8_BITS TFFSCPY_TO_IO +#else +#define TFFSCPY_TO_IO_8_BITS(dest,src,count) tffscpy((void FAR0*)(dest),src,count) +#endif +#endif /* TFFSCPY_TO_IO_8_BITS */ + +#ifndef TFFSCPY_TO_IO_16_BITS +#ifdef TFFSCPY_TO_IO +#define TFFSCPY_TO_IO_16_BITS TFFSCPY_TO_IO +#else +#define TFFSCPY_TO_IO_16_BITS(dest,src,count) tffscpy((void FAR0*)(dest),src,count) +#endif +#endif /* TFFSCPY_TO_IO_16_BITS */ + +#ifndef TFFSSET_IO_8_BITS +#ifdef TFFSSET_IO +#define TFFSSET_IO_8_BITS TFFSSET_IO +#else +#define TFFSSET_IO_8_BITS(dest,val,count) tffsset((void FAR0*)(dest),val,count) +#endif +#endif /* TFFSSET_IO_8_BITS */ + +#ifndef TFFSSET_IO_16_BITS +#ifdef TFFSSET_IO +#define TFFSSET_IO_16_BITS TFFSSET_IO +#else +#define TFFSSET_IO_16_BITS(dest,val,count) tffsset((void FAR0*)(dest),val,count) +#endif +#endif /* TFFSSET_IO_16_BITS */ + +/* The FAT-LITE/SURE-FS API definitions were added the FL_ prefix. + * + * Starting from TrueFFS 6.2 + */ + + +#ifndef FS_FILES +#ifdef FILES +#define FS_FILES FILES +#endif /* FILES */ +#ifdef FL_FILES +#define FS_FILES FL_FILES +#endif /* FL_FILES */ +#endif /* FS_FILES */ + +#if defined(FS_FILES) && (FS_FILES <= 0) +#undef FS_FILES +#endif + +#if defined(FS_MAX_FSOS) && ((FS_MAX_FSOS <= 0) || !defined(FS_FILES)) +#undef FS_MAX_FSOS +#endif + +#if defined(FS_SUPPORT_FILE_CACHE) && !defined(FS_MAX_FSOS) +#undef FS_SUPPORT_FILE_CACHE +/* you need FSOs to define the cache size per file type */ +#endif + +#if defined(FS_SUPPORT_FILE_CACHE) && !defined(FL_EXTENDED_SECTOR_CACHE) +#define FL_EXTENDED_SECTOR_CACHE +#endif + +#if defined(FS_MAX_FSOS) && !defined(FS_MM_PERFORMANCE_TUNEUPS) +#define FS_MM_PERFORMANCE_TUNEUPS +#endif + +#if defined(FS_MAX_FSOS) && !defined(STATIC_FS_DB) +#if FS_MAX_FSOS >= 2 +#define STATIC_FS_DB = { DEFAULT_FILE(0, 0), DEFINE_FSO(NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) } +#else +#define STATIC_FS_DB = { DEFAULT_FILE(0, 0) } +#endif +#endif + +#if defined(SUB_DIRECTORY) && !defined(FS_SUB_DIRECTORY) +#define FS_SUB_DIRECTORY +#endif + +#if defined(RENAME_FILE) && !defined(FS_RENAME_FILE) +#define FS_RENAME_FILE +#endif + +#ifndef FILE_IS_ROOT_DIR +#define FILE_IS_ROOT_DIR FL_FILE_IS_ROOT_DIR +#endif + +#ifndef FILE_MODIFIED +#define FILE_MODIFIED FL_FILE_MODIFIED +#endif + +#ifndef FILE_IS_OPEN +#define FILE_IS_OPEN FL_FILE_IS_OPEN +#endif + +#ifndef FILE_IS_DIRECTORY +#define FILE_IS_DIRECTORY FL_FILE_IS_DIRECTORY +#endif + +#ifndef FILE_READ_ONLY +#define FILE_READ_ONLY FL_FILE_READ_ONLY +#endif + +#ifndef FILE_MUST_OPEN +#define FILE_MUST_OPEN FL_FILE_MUST_OPEN +#endif + + +#if defined(FL_TRANSLATE_FROM_UNICODE) && defined(FL_TRANSLATE_TO_UNICODE) +#define FILENAMES_INTERNAL_UNICODE_CONVERSION /* user-defined functions */ + +#elif defined(FL_LONG_FILENAMES_ASCII_SUPPORT) +#define FL_TRANSLATE_FROM_UNICODE unicodeToAscii +#define FL_TRANSLATE_TO_UNICODE asciiToUnicode + +#define FILENAMES_INTERNAL_UNICODE_CONVERSION + +#elif defined(FL_LONG_FILENAMES_UTF8_SUPPORT) +#define FL_TRANSLATE_FROM_UNICODE unicodeToUTF8 +#define FL_TRANSLATE_TO_UNICODE UTF8ToUnicode + +#define FILENAMES_INTERNAL_UNICODE_CONVERSION + +#endif + +#if defined(FL_EXTENDED_SECTOR_CACHE) && (!defined(FS_FILES) || (FS_FILES == 0)) +#undef FL_EXTENDED_SECTOR_CACHE +#endif + +#if defined(FL_EXTENDED_SECTOR_CACHE) && !defined(FS_DATA_CACHE_SIZE) +#define FS_DATA_CACHE_SIZE(socket, partition, logPartition) 200 +#endif + +#if defined(FAT_12BIT) && !defined(FS_FAT_12BIT) +#define FS_FAT_12BIT +#endif + +/******************************** MTD Macros ********************************************/ + +#ifndef FL_CHANGE_READ_ACCESS_TIME +#define FL_CHANGE_READ_ACCESS_TIME(wTimeNanoSec,socket) +#endif /* FL_CHANGE_READ_ACCESS_TIME */ + +/****************************************************************************************/ +/******************************* M I G R A T I O N M A C R O S ***********************/ +/****************************************************************************************/ + +/* Maximum number of supported DOCHs */ +/*===================================*/ +#ifndef DOCH_MAX_SOCKETS + #ifdef FL_SOCKETS + #define DOCH_MAX_SOCKETS FL_SOCKETS + #else /*FL_SOCKETS*/ + #define DOCH_MAX_SOCKETS 1 + #endif /*FL_SOCKETS*/ +#endif /*DOCH_MAX_SOCKETS*/ + +/* + * Length of DOCH register 'read' cycle in nanoseconds (default value should + * do for most systems). + */ +#ifndef DOCH_ACCESS_NANOSEC + #define DOCH_ACCESS_NANOSEC 15 +#endif /*DOCH_ACCESS_NANOSEC*/ + +#ifndef DOCH_SPI_ACCESS_NANOSEC + #define DOCH_SPI_ACCESS_NANOSEC 150000 +#endif /*DOCH_SPI_ACCESS_NANOSEC*/ + +/* Host CPU ENDIANESS */ +/*====================*/ +#ifndef DOCH_BIG_ENDIAN + #ifdef FL_BIG_ENDIAN + #define DOCH_BIG_ENDIAN + #endif /*FL_BIG_ENDIAN*/ +#endif /*DOCH_BIG_ENDIAN*/ + + +/*DOCH specific power mode defaults */ +/*================================= */ +/* by default DPD configured to: + active mode is NORMAL, + after command execution, device passes immediatly to + IDLE mode and after timeout (100msec) to DPD mode*/ +#ifndef DOCH_DPD_DEFAULT_ACTIVE_MODE + #define DOCH_DPD_DEFAULT_ACTIVE_MODE DOCH_WM_NORMAL_AND_AUTO_STBY /*DOCH_WorkMode*/ +#endif /*DOCH_DPD_DEFAULT_ACTIVE_MODE*/ + +#ifndef DOCH_DPD_DEFAULT_INACTIVE_MODE + #define DOCH_DPD_DEFAULT_INACTIVE_MODE DOCH_IM_IDLE_2_DPD /*DOCH_InactiveMode*/ +#endif /*DOCH_DPD_DEFAULT_INACTIVE_MODE*/ + +#ifndef DOCH_DPD_DEFAULT_DPD_TIMEOUT + #define DOCH_DPD_DEFAULT_DPD_TIMEOUT 1 +#endif /*DOCH_DPD_DEFAULT_DPD_TIMEOUT*/ +/*================================= */ +/* end of DOCH power mode settings */ + + +/* Memory allocation */ +/*===================*/ +#ifndef DOCH_MALLOC + #ifdef FL_MALLOC + #define DOCH_MALLOC FL_MALLOC + #endif /*FL_MALLOC*/ +#endif /*DOCH_MALLOC*/ + +#ifndef DOCH_FREE + #ifdef FL_FREE + #define DOCH_FREE FL_FREE + #endif /*FL_FREE*/ +#endif /*DOCH_FREE*/ + +/* System init/release functions */ +/*===============================*/ +#ifndef DOCH_SYS_FUNC_INIT +#define DOCH_SYS_FUNC_INIT +#endif /* DOCH_SYS_FUNC_INIT */ + +#ifndef DOCH_SYS_FUNC_RELEASE + #ifdef FL_SYS_FUNC_RELEASE + #define DOCH_SYS_FUNC_RELEASE FL_SYS_FUNC_RELEASE + #else /*FL_SYS_FUNC_RELEASE*/ + #define DOCH_SYS_FUNC_RELEASE() + #endif /*FL_SYS_FUNC_RELEASE*/ +#endif /*DOCH_SYS_FUNC_RELEASE*/ + +/* DMA transfer */ +/*==============*/ +#ifndef DOCH_DMA_CONFIG + #ifdef FL_DMA_CONFIG + #define DOCH_DMA_CONFIG FL_DMA_CONFIG + #endif /*FL_DMA_CONFIG*/ +#endif + + +/* DMA type flags - FL_DMA_CONFIG */ +/*===================================*/ +/* Note: DMA_Params_S is defined in flsystyp.h */ +#define DOCH_DMA_OPEN_CHANNEL 0 +#define DOCH_DMA_CONFIG_TRANSACTION_DEVICE_TO_HOST 1 +#define DOCH_DMA_FREE_CHANNEL 2 +#define DOCH_DMA_WAIT_FOR_READ_TRANSACTION_END 3 +#define DOCH_DMA_WAIT_FOR_WRITE_TRANSACTION_END 4 +#define DOCH_DMA_CONFIG_TRANSACTION_HOST_TO_DEVICE 5 + +#define DMA_OPEN_CHANNEL DOCH_DMA_OPEN_CHANNEL +#define DMA_CONFIG_TRANSACTION DOCH_DMA_CONFIG_TRANSACTION_DEVICE_TO_HOST +#define DMA_FREE_CHANNEL DOCH_DMA_FREE_CHANNEL +#define DMA_WAIT_FOR_TRANSACTION_END DOCH_DMA_WAIT_FOR_READ_TRANSACTION_END +#define DMA_CONFIG_WRITE_TRANSACTION DOCH_DMA_CONFIG_TRANSACTION_HOST_TO_DEVICE +#define DMA_WAIT_FOR_WRITE_TRANSACTION_END DOCH_DMA_WAIT_FOR_WRITE_TRANSACTION_END + +#ifndef DOCH_DMA_PULSE_WIDTH + #define DOCH_DMA_PULSE_WIDTH 0x001F +#endif /*DOCH_DMA_PULSE_WIDTH*/ + +/* DOCH_DMA_CHECK_BUFFER checks if buffer is suitable for DMA transfer*/ +#ifndef DOCH_DMA_CHECK_BUFFER + #define DOCH_DMA_CHECK_BUFFER(bufAddress, sectors) (((FLDword)bufAddress & 0x3) == 0) +#endif /*DOCH_DMA_CHECK_BUFFER*/ + +/* Burst Mode */ +/*============*/ + +#ifndef DOCH_USE_BURST_MODE_READ + #ifdef FL_USE_BURST_MODE_READ + #define DOCH_USE_BURST_MODE_READ + #endif /*FL_USE_BURST_MODE_READ*/ +#endif /*DOCH_USE_BURST_MODE_READ*/ + +#ifdef DOCH_USE_BURST_MODE_READ + + #ifndef DOCH_USE_BURST_MODE_READ_ONLY_IN_DMA + #ifdef FL_USE_BURST_MODE_READ_ONLY_IN_DMA + #define DOCH_USE_BURST_MODE_READ_ONLY_IN_DMA + #endif /*FL_USE_BURST_MODE_READ*/ + #endif /*DOCH_USE_BURST_MODE_READ*/ + + #ifndef DOCH_HOST_ENTER_READ_BURST_MODE + #ifdef FL_HOST_ENTER_BURST_MODE + #define DOCH_HOST_ENTER_READ_BURST_MODE FL_HOST_ENTER_BURST_MODE + #else /*FL_HOST_ENTER_BURST_MODE*/ + #define DOCH_HOST_ENTER_READ_BURST_MODE + #endif /*FL_HOST_ENTER_BURST_MODE*/ + #endif /*DOCH_HOST_ENTER_READ_BURST_MODE*/ + + #ifndef DOCH_HOST_EXIT_READ_BURST_MODE + #ifdef FL_HOST_EXIT_BURST_MODE + #define DOCH_HOST_EXIT_READ_BURST_MODE FL_HOST_EXIT_BURST_MODE + #else /*FL_HOST_EXIT_BURST_MODE*/ + #define DOCH_HOST_EXIT_READ_BURST_MODE + #endif /*FL_HOST_EXIT_BURST_MODE*/ + #endif /*DOCH_HOST_EXIT_READ_BURST_MODE*/ + + #ifndef DOCH_READ_STATUS_ASYNC_IN_BURST + #ifdef FL_READ_STATUS_ASYNC_IN_BURST + #define DOCH_READ_STATUS_ASYNC_IN_BURST + #endif /*FL_READ_STATUS_ASYNC_IN_BURST*/ + #endif /*DOCH_READ_STATUS_ASYNC_IN_BURST*/ + +#endif /*DOCH_USE_BURST_MODE_READ*/ + +#ifdef DOCH_USE_BURST_MODE_WRITE + + #ifndef DOCH_HOST_ENTER_WRITE_BURST_MODE + #define DOCH_HOST_ENTER_WRITE_BURST_MODE + #endif /*DOCH_HOST_ENTER_WRITE_BURST_MODE*/ + + #ifndef DOCH_HOST_EXIT_WRITE_BURST_MODE + #define DOCH_HOST_EXIT_WRITE_BURST_MODE + #endif /*DOCH_HOST_EXIT_WRITE_BURST_MODE*/ + +#endif /*DOCH_USE_BURST_MODE_WRITE*/ + +#ifndef DOCH_BURST_LENGTH + #ifdef BURST_LENGTH + #define DOCH_BURST_LENGTH ( (((BURST_LENGTH)-2)& 0x03 ) <<11) + #else + #ifdef FL_USE_BURST_MODE_READ + #ifdef FL_MIGRATION_VERSION + #error BURST_LENGTH must be defined, when FL_USE_BURST_MODE_READ defined + #else + #error DOCH_BURST_LENGTH must be defined, when DOCH_USE_BURST_MODE_READ defined + #endif /* migration*/ + #endif /*FL_USE_BURST_MODE_READ*/ + #endif /* BURST_LENGTH */ +#endif /*DOCH_BURST_LENGTH*/ + +#ifndef DOCH_BURST_LATENCY + #ifdef BURST_LATENCY + #define DOCH_BURST_LATENCY ( ((BURST_LATENCY)& 0x07 )<<8) + #else + #ifdef FL_USE_BURST_MODE_READ + #ifdef FL_MIGRATION_VERSION + #error BURST_LATENCY must be defined, when FL_USE_BURST_MODE_READ defined + #else + #error DOCH_BURST_LATENCY must be defined, when DOCH_USE_BURST_MODE_READ defined + #endif /* migration*/ + #endif /*FL_USE_BURST_MODE_READ*/ + #endif /* BURST_LENGTH */ +#endif /*DOCH_BURST_LATENCY*/ + +#ifndef DOCH_BURST_HOLD + #ifdef BURST_HOLD + #define DOCH_BURST_HOLD ((BURST_HOLD)<<13) + #else + #ifdef FL_USE_BURST_MODE_READ + #ifdef FL_MIGRATION_VERSION + #error BURST_HOLD must be defined, when FL_USE_BURST_MODE_READ defined + #else + #error DOCH_BURST_HOLD must be defined, when DOCH_USE_BURST_MODE_READ defined + #endif /* migration*/ + #endif /*FL_USE_BURST_MODE_READ*/ + #endif /* BURST_HOLD */ +#endif /*DOCH_BURST_HOLD*/ + +#ifndef DOCH_BURST_WAIT_STATE + #ifdef BURST_WAIT_STATE + #define DOCH_BURST_WAIT_STATE ( ((BURST_WAIT_STATE)&0x03 )<<4) + #else + #ifdef FL_USE_BURST_MODE_READ + #ifdef FL_MIGRATION_VERSION + #error BURST_WAIT_STATE must be defined, when FL_USE_BURST_MODE_READ defined + #else + #error DOCH_BURST_WAIT_STATE must be defined, when DOCH_USE_BURST_MODE_READ defined + #endif /* migration*/ + #endif /*FL_USE_BURST_MODE_READ*/ + #endif +#endif /*DOCH_BURST_WAIT_STATE*/ + +/* end of BURST definitions for H3 */ +/*=================================*/ + + + +/* Interrupt enabling */ +/*====================*/ + +#define DOCH_INT_RB_DISABLED 0x00 +#define DOCH_INT_RB_ENABLED 0x01 + +#ifndef DOCH_IRQ_RB_INIT + #ifdef FL_IRQ_RB_INIT + #define DOCH_IRQ_RB_INIT(wSockeNo) FL_IRQ_RB_INIT((wSockeNo)) + #else /*FL_IRQ_RB_INIT*/ + #define DOCH_IRQ_RB_INIT(wSockeNo) gDochIrqEnabled[(wSockeNo)] + #endif /*FL_IRQ_RB_INIT*/ +#endif /*DOCH_IRQ_RB_INIT*/ + +/* MACRO for "Wait on Interrupt" */ +/*===============================*/ +#ifndef DOCH_SLEEP + #ifdef FL_TFFS_SLEEP + #define DOCH_SLEEP(socket, device, microseconds) FL_TFFS_SLEEP(socket, microseconds) + #else + #define DOCH_SLEEP(socket, device, microseconds) + #endif /*FL_TFFS_SLEEP*/ +#endif /*DOCH_SLEEP*/ + +/* MACRO for notifying application that an interrupt had occurred + and was NOT yet serviced */ +/*==========================*/ +#ifndef DOCH_UNSERVICED_INTERRUPT + #define DOCH_UNSERVICED_INTERRUPT(socket, device) DOCH_SLEEP(socket, device, 0) +#endif /*DOCH_UNSERVICED_INTERRUPT*/ + + +/* DOCH HW Configuration defaults */ +/*================================*/ + +#ifndef DOCH_BURST_WRITE_MODE_DEFAULT + #define DOCH_BURST_WRITE_MODE_DEFAULT (DOCH_BURST_DISABLE | DOCH_BURST_HOLD_1_CLK | DOCH_BURST_LEN_4_CYC) +#endif /*DOCH_BURST_WRITE_MODE_DEFAULT*/ + +#ifndef DOCH_BURST_READ_MODE_DEFAULT + #define DOCH_BURST_READ_MODE_DEFAULT (DOCH_BURST_DISABLE | DOCH_BURST_HOLD_1_CLK | DOCH_BURST_LEN_4_CYC) +#endif /*DOCH_BURST_READ_MODE_DEFAULT*/ + +#ifndef DOCH_IPL_CTRL_DEFAULT + #define DOCH_IPL_CTRL_DEFAULT (DOCH_IPL_WRITE_DISABLE | DOCH_IPL_ALL_CS_ENABLED) +#endif /*DOCH_IPL_CTRL_DEFAULT*/ + +#ifndef DOCH_WARM_BOOT_CTRL_DEFAULT + #define DOCH_WARM_BOOT_CTRL_DEFAULT (DOCH_WARM_RST_POLARITY_HIGH | DOCH_WARM_RST_BURST_ON) +#endif /*DOCH_WARM_BOOT_CTRL_DEFAULT*/ + +#ifndef DOCH_POWER_DOWN_DEFAULT + #define DOCH_POWER_DOWN_DEFAULT (DOCH_DPD_PIN_POL_HIGH | DOCH_DPD_PIN_ENABLED | DOCH_DPD_WAKEUP_HOST_CE) +#endif /*DOCH_POWER_DOWN_DEFAULT*/ + +#ifndef DOCH_DMA_CTRL_DEFAULT + #define DOCH_DMA_CTRL_DEFAULT (DOCH_DMA_REQ_POL_LOW | DOCH_DMA_REQ_EDGE | ((DOCH_DMA_PULSE_WIDTH)<<4)) +#endif /*DOCH_DMA_CTRL_DEFAULT*/ + +#ifndef DOCH_DMA_NEGATION_CTRL_DEFAULT + #define DOCH_DMA_NEGATION_CTRL_DEFAULT 1 +#endif /*DOCH_DMA_NEGATION_CTRL_DEFAULT*/ + +#ifndef DOCH_SLOCK_DEFAULT + #define DOCH_SLOCK_DEFAULT DOCH_SLOCK_OFF +#endif /*DOCH_SLOCK_DEFAULT*/ + +#ifndef DOCH_ENDIAN_CTRL_DEFAULT + #ifdef FL_SWAP_BYTES + #define DOCH_ENDIAN_CTRL_DEFAULT (HIB_END_SWAP_ON) + #else /*FL_SWAP_BYTES*/ + #define DOCH_ENDIAN_CTRL_DEFAULT (HIB_END_SWAP_OFF) + #endif /*FL_SWAP_BYTES*/ +#endif /*DOCH_ENDIAN_CTRL_DEFAULT*/ + +#ifndef DOCH_OPERATION_MODE_CTRL_DEFAULT + #define DOCH_OPERATION_MODE_CTRL_DEFAULT (HIB_ADDR_SHIFT | HIB_NON_PIPE_ACCESS) +#endif /*DOCH_OPERATION_MODE_CTRL_DEFAULT*/ + + +/*Max number of devices per ATA socket (defined by ATA standard)*/ +#ifndef ATA_MAX_NUM_OF_DEVICES /* for mDOC H3 devices only */ + #define ATA_MAX_NUM_OF_DEVICES 1 /* should be 1 or 2 */ +#endif /* ATA_MAX_NUM_OF_DEVICES */ + +/*If a wait is needed between identifying Dev0 and Dev1, customize DOCH_WAIT_B4_DEV1_ID*/ +#ifndef DOCH_WAIT_B4_DEV1_ID + #define DOCH_WAIT_B4_DEV1_ID +#endif /*DOCH_WAIT_B4_DEV1_ID*/ + +/*If a wait is needed after switching between Dev0 and Dev1, customize DOCH_DELAY_USEC*/ +#ifndef DOCH_DELAY_USEC +#ifdef FL_DELAY_USEC + #define DOCH_DELAY_USEC(usec) FL_DELAY_USEC(usec) +#else + #define DOCH_DELAY_USEC(usec) def_dochDelayUsec(usec,gDochAccessNanosec) +#endif /*FL_DELAY_USEC*/ +#endif /*DOCH_DELAY_USEC*/ + +#ifndef DOCH_DELAY_MSEC +#ifdef FL_DELAY_MSEC + #define DOCH_DELAY_MSEC(msec) FL_DELAY_MSEC(msec) +#else + #define DOCH_DELAY_MSEC(msec) def_dochDelayUsec(1000*msec,gDochAccessNanosec) +#endif /*FL_DELAY_MSEC*/ +#endif /*DOCH_DELAY_MSEC*/ + +/*Accessing same register twice requires delay*/ +#ifndef FL_DELAY_BEFORE_ACCESSING_SAME_REGISTER + #define DOCH_DELAY_BEFORE_ACCESSING_SAME_REGISTER \ + def_dochDelayUsec(4,25) +#else + #define DOCH_DELAY_BEFORE_ACCESSING_SAME_REGISTER \ + FL_DELAY_BEFORE_ACCESSING_SAME_REGISTER +#endif /*FL_DELAY_BEFORE_ACCESSING_SAME_REGISTER*/ + +#if (ATA_MAX_NUM_OF_DEVICES == 2) + + #ifndef FL_SUPPORT_PARALLEL_SDK_INSTANCES + #define DOCH_NO_SUPPORT_PARALLEL_SDK_INSTANCES + #endif /*FL_SUPPORT_PARALLEL_SDK_INSTANCES*/ + + /*cascaded configuration requires delay after switching between Dev0 and Dev1*/ + #ifndef DOCH_DELAY_AFTER_DEVICE_SWITCH + #ifdef DOCH_NO_SUPPORT_PARALLEL_SDK_INSTANCES + /* delay only when switching floors */ + #define DOCH_DELAY_AFTER_DEVICE_SWITCH(pdev,floorNo)\ + if ((pdev)->bLastDevNum ^ (floorNo))\ + { \ + DOCH_DELAY_USEC(4); \ + (pdev)->bLastDevNum = (floorNo);\ + } + #else /*DOCH_SUPPORT_PARALLEL_SDK_INSTANCES*/ + /* always delay after setting device head register */ + #define DOCH_DELAY_AFTER_DEVICE_SWITCH(pdev,floorNo)\ + DOCH_DELAY_USEC(4) /* 4 uSec delay */ + #endif /*DOCH_SUPPORT_PARALLEL_SDK_INSTANCES*/ + #endif /*DOCH_DELAY_AFTER_DEVICE_SWITCH*/ + + /*cascaded configuration requires delay after each trial of reading chip ID from SLAVE*/ + #ifndef DOCH_DELAY_BETWEEN_CHIP_ID_TRIALS_FOR_SLAVE + #define DOCH_DELAY_BETWEEN_CHIP_ID_TRIALS_FOR_SLAVE DOCH_DELAY_MSEC(1) /* 1 mSec delay*/ + #endif /*DOCH_DELAY_BETWEEN_CHIP_ID_TRIALS_FOR_SLAVE*/ + + /*cascaded configuration requires several trials of reading chip ID*/ + /* 2 seconds timeout for finding SLAVE ~ 2000 trials * 1mSec delay */ + #ifndef DOCH_CHIP_ID_TRIALS_FOR_SLAVE + #define DOCH_CHIP_ID_TRIALS_FOR_SLAVE DOCH_MOUNT_WAIT + #endif /*DOCH_CHIP_ID_TRIALS_FOR_SLAVE*/ + +#else /*if (ATA_MAX_NUM_OF_DEVICES == 2)*/ + /* single floor does not require any delays*/ + + #ifndef DOCH_DELAY_AFTER_DEVICE_SWITCH + #define DOCH_DELAY_AFTER_DEVICE_SWITCH(pdev,floorNo) /*no delay is needed*/ + #endif /*DOCH_DELAY_AFTER_DEVICE_SWITCH*/ + + #ifndef DOCH_DELAY_BETWEEN_CHIP_ID_TRIALS_FOR_SLAVE + #define DOCH_DELAY_BETWEEN_CHIP_ID_TRIALS_FOR_SLAVE /*no delay is needed*/ + #endif /*DOCH_DELAY_BETWEEN_CHIP_ID_TRIALS_FOR_SLAVE*/ + + #ifndef DOCH_CHIP_ID_TRIALS_FOR_SLAVE + #define DOCH_CHIP_ID_TRIALS_FOR_SLAVE 0 /* no trials for reading second floor*/ + #endif /*DOCH_CHIP_ID_TRIALS_FOR_SLAVE*/ + +#endif /*if (ATA_MAX_NUM_OF_DEVICES == 2)*/ + +/* Delay cell configuration*/ +/* +0000: No Delay +0001: 1x delay. +0011: 2x delay. +0111: 3x delay. +*/ + +#ifndef FL_IPL_DELAY_CELL_CONFIG_READ + #define FL_IPL_DELAY_CELL_CONFIG_READ 0 +#endif /*FL_IPL_DELAY_CELL_CONFIG_READ*/ + +#ifndef FL_IPL_DELAY_CELL_CONFIG_WRITE + #define FL_IPL_DELAY_CELL_CONFIG_WRITE 0 +#endif /*FL_IPL_DELAY_CELL_CONFIG_READ*/ + + +/*===========================*/ +/* Access Layer Customization*/ +/* --------------------------*/ +/* 2 Sections: */ +/* - Run-Time */ +/* - Compile Time */ +/*===========================*/ +#ifdef DOCH_BIG_ENDIAN +#define C_16_8(a) ((FLByte)((a)>>8)) +#define C_8_16(a) (((FLWord)(a))<<8) +#define C_16_16(a) ((FLWord)((a)<<8) | ((a)>>8)) +#else +#define C_16_8(a) ((FLByte)(a)) +#define C_8_16(a) ((FLWord)(a)) +#define C_16_16(a) ((FLWord)(a)) +#endif /* DOCH_BIG_ENDIAN */ + +#ifdef DOCH_USE_FUNC /*Run-time*/ + +/* DOCH Access Layer macros */ +/*==========================*/ +#ifndef DOCHREAD_ATA_REG +#define DOCHREAD_ATA_REG(base, regNum) C_16_8(pdev->halRoutines.hal_get_ata_reg(base, regNum)) +#endif /*DOCHREAD_ATA_REG*/ +#ifndef DOCHWRITE_ATA_REG +#define DOCHWRITE_ATA_REG(base, regNum, val) (pdev->halRoutines.hal_set_ata_reg(base, regNum, C_8_16(val))) +#endif /*DOCHWRITE_ATA_REG*/ +#ifndef DOCHREAD_CTRL_REG +#define DOCHREAD_CTRL_REG(base, regNum) C_16_16(pdev->halRoutines.hal_get_ctrl_reg(base, regNum)) +#endif /*DOCHREAD_CTRL_REG*/ +#ifndef DOCHWRITE_CTRL_REG +#define DOCHWRITE_CTRL_REG(base, regNum, val) (pdev->halRoutines.hal_set_ctrl_reg(base, regNum, C_16_16(val))) +#endif /*DOCHWRITE_CTRL_REG*/ +#ifndef DOCHBLK_READ +#define DOCHBLK_READ(address, buf, sectors) (pdev->halRoutines.hal_blk_read(address, buf, sectors)) +#endif /*DOCHBLK_READ*/ +#ifndef DOCHBLK_WRITE +#define DOCHBLK_WRITE(address, buf, sectors) (pdev->halRoutines.hal_blk_write(address, buf, sectors)) +#endif /*DOCHBLK_WRITE*/ + +#ifndef DOCHREAD_BURST + #define DOCHREAD_BURST(base, offset, dest, sectors) +#endif /*DOCHREAD_BURST*/ + +#ifndef DOCHWRITE_BURST + #define DOCHWRITE_BURST(base, offset, dest, sectors) +#endif /*DOCHWRITE_BURST*/ + + /* DOCH IO Access macros */ + /*=======================*/ + #ifndef DOCHREAD_IO_WORD + #define DOCHREAD_IO_WORD(address) (FLREAD_IO_WORD(address)) + #endif /*DOCHREAD_IO_WORD*/ + + #ifndef DOCHWRITE_IO_WORD + #define DOCHWRITE_IO_WORD(val, address) (FLWRITE_IO_WORD(val, address)) + #endif /*DOCHWRITE_IO_WORD*/ + + #ifndef DOCHCPY_TO_IO_16_BITS + #define DOCHCPY_TO_IO_16_BITS(win,buf,sectors) (blk_write_using_data_reg(win, buf, sectors)) + #endif /*DOCHCPY_TO_IO_16_BITS*/ + + #ifndef DOCHCPY_FROM_IO_16_BITS + #define DOCHCPY_FROM_IO_16_BITS(win,buf,sectors) (blk_read_using_data_reg(win, buf, sectors)) + #endif /*DOCHCPY_FROM_IO_16_BITS*/ + +#else /*DOCH_USE_FUNC*/ /*Compile-Time*/ +#ifdef FL_MIGRATION_VERSION +/* DOCH Access Layer macros */ +/*==========================*/ +#ifndef DOCHREAD_ATA_REG +#define DOCHREAD_ATA_REG(base, regNum) C_16_8(flDirectRead16BitReg((DOCHFlash),(FLWord)(((regNum)<<1) + DOCH_CONT_REG_AREA))) +#endif /*DOCHREAD_ATA_REG*/ +#ifndef DOCHWRITE_ATA_REG +#define DOCHWRITE_ATA_REG(base, regNum, val) flDirectWrite16BitReg((DOCHFlash),(FLWord)(((regNum)<<1) + DOCH_CONT_REG_AREA),(FLWord)(C_8_16(val))) +#endif /*DOCHWRITE_ATA_REG*/ +#ifndef DOCHREAD_CTRL_REG +#define DOCHREAD_CTRL_REG(base, regNum) C_16_16(flDirectRead16BitReg((DOCHFlash),(FLWord)(regNum))) +#endif /*DOCHREAD_CTRL_REG*/ +#ifndef DOCHWRITE_CTRL_REG +#define DOCHWRITE_CTRL_REG(base, regNum, val) flDirectWrite16BitReg((DOCHFlash),(FLWord)(regNum),(FLWord)(C_16_16(val))) +#endif /*DOCHWRITE_CTRL_REG*/ +#ifndef DOCHBLK_READ +#define DOCHBLK_READ(address, buf, sectors) (flReadEvenNumberOfBytes((DOCHFlash),(FLWord)DOCH_DATA_PORT_AREA,(buf),((FLWord)(512*sectors))),0) +#endif /*DOCHBLK_READ*/ +#ifndef DOCHBLK_WRITE +#define DOCHBLK_WRITE(address, buf, sectors) (flWriteEvenNumberOfBytes((DOCHFlash),(FLWord)DOCH_DATA_PORT_AREA,(buf),((FLWord)(512*sectors))),0) +#endif /*DOCHBLK_WRITE*/ + +#ifndef DOCHREAD_BURST +#define DOCHREAD_BURST(base, offset, dest, sectors) DOCHBLK_READ( (base)+(offset), dest, sectors) +#endif /*DOCHREAD_BURST*/ + +#ifndef DOCHWRITE_BURST +#define DOCHWRITE_BURST(base, offset, dest, sectors) DOCHBLK_WRITE( (base)+(offset), dest, sectors) +#endif /*DOCHWRITE_BURST*/ + + +/* DOCH IO Access macros */ +/*=======================*/ +/* Not defined as we use legacy code */ + +#else /* FL_MIGRATION_VERSION */ + + #ifndef DOCHREAD_ATA_REG + #define DOCHREAD_ATA_REG(base, regNum) \ + (FLByte)(DOCHREAD_IO_WORD((((volatile FLWord FAR0 *)base)+regNum + (DOCH_CONT_REG_AREA/2)))) + #endif /*DOCHREAD_ATA_REG*/ + + #ifndef DOCHWRITE_ATA_REG + #define DOCHWRITE_ATA_REG(base, regNum, val) \ + DOCHWRITE_IO_WORD((FLWord)val,(((volatile FLWord FAR0 *)base)+regNum + (DOCH_CONT_REG_AREA/2))) + #endif /*DOCHWRITE_ATA_REG*/ + + #ifndef DOCHREAD_CTRL_REG + #define DOCHREAD_CTRL_REG(base, regNum) \ + DOCHREAD_IO_WORD(base + regNum) + #endif /*DOCHREAD_CTRL_REG*/ + + #ifndef DOCHWRITE_CTRL_REG + #define DOCHWRITE_CTRL_REG(base, regNum, val) \ + DOCHWRITE_IO_WORD((FLWord)val, (base + regNum)) + + #endif /*DOCHWRITE_CTRL_REG*/ + + #ifndef DOCHBLK_READ + #define DOCHBLK_READ(address, buf, sectors) \ + DOCHCPY_FROM_IO_16_BITS(address, buf, sectors) + #endif /*DOCHBLK_READ*/ + + #ifndef DOCHBLK_WRITE + #define DOCHBLK_WRITE(address, buf, sectors) \ + DOCHCPY_TO_IO_16_BITS(address, buf, sectors) + #endif /*DOCHBLK_WRITE*/ + + /* DOCH IO Access macros */ + /*=======================*/ + #ifndef DOCHREAD_IO_WORD + #define DOCHREAD_IO_WORD(address) (FLREAD_IO_WORD(address)) + #endif /*DOCHREAD_IO_WORD*/ + + #ifndef DOCHWRITE_IO_WORD + #define DOCHWRITE_IO_WORD(val, address) (FLWRITE_IO_WORD(val, address)) + #endif /*DOCHWRITE_IO_WORD*/ + + #ifndef DOCHCPY_TO_IO_16_BITS + #define DOCHCPY_TO_IO_16_BITS(win,buf,sectors) TFFSCPY_TO_IO_16_BITS(win,buf,(sectors<dwVirtAddr) != flOK ) + { + PrintkDebug ("mDOC not found"); + return flAdapterNotFound; + } + + PrintkInfo ("mDOC found"); + psoc->fFound = 1; + + return flOK; +} + + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/flcustom.h linux-2.6.30.4/drivers/block/tffs/flcustom.h --- linux-2.6.30.4-orig/drivers/block/tffs/flcustom.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/flcustom.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,386 @@ +/****************************************************************************** + * * + * Project: DOC Driver for Linux 2.6 Block device driver for mDOC H3 family * + * of devices under Linux kernel 2.6. * + * * + * Version: 1.0 * + * Email questions to: oemsupport@sandisk.com * + * Copyright (C) SanDisk IL Ltd. 1995 - 2007 * + * SanDisk IL Ltd., 7 Atir Yeda Street, Kfar Saba 44425, Israel * + * * + ****************************************************************************** + * * + * 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 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, which is set forth in the readme.txt file. * + * 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., 51 * + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + * * + * This License does not grant you any right to use the trademarks, service * + * marks or logos of SanDisk IL Ltd. or SanDisk Corporation. * + * Subject to the foregoing, SanDisk IL Ltd., for itself and on behalf of its * + * licensors, hereby reserves all intellectual property rights in the program,* + * except for the rights expressly granted in this License. * + * * + ******************************************************************************/ + +/* + * $Log$ + */ + + + +#ifndef FLCUSTOM_H +#define FLCUSTOM_H + + +/* Driver & TrueFFS Version numbers (Previously named OSAK) + * + * The string must not be greater than 10 characters. + * + * Note: Other then being returned by the the flVolumeInfo() routine this + * value has no actual affect on the TrueFFS software. + */ +#define driverVersion "1.1.0" +#define OSAKVersion "1.1.0" + + +#define TFFS_SUPPORTED_DEVICE "H3" + + +/* + * debug/diagnostic messages + */ +#define TFFS_DEBUG_DRIVER + +#ifdef TFFS_DEBUG_DRIVER + +/* EXT filter debug messages */ +# define TFFS_DEBUG_EXTFILTER + +/* enable TFFS debug messages and fl_debug insmod argument */ +# define TFFS_MESSAGES_ENABLED + +/* default for fl_debug parameter: 0 - no messages, 1 - errors, 2 - warnings, 4 - flow */ +# define FL_DEBUG_DEF 2 + +/* #define TFFS_COUNT_REQ_SECTORS */ + +#endif /* TFFS_DEBUG_DRIVER */ + + +/* + * Collect various driver statistics + */ +#define TFFS_STATISTIC + + +/* + * comment out this macro if you want to get "MTD-style" + */ +#define TFFS_PARTITIONABLE + + +/* + * Scatter/gather of read/write requests in tffsdrv.c + */ +#define TFFS_REQ_CACHE_SIZE (4096 * 16) + + +#define DEV2PART_SHIFT 4 /* at most 15 file system partitions per disk */ +#define TFFS_DEVICE_NAME "tffs" +#define TFFS_MAXHW_SECTOR_SIZE_BITS 0 + + +/* + * allow using of unformatted DiskOnChip devices + */ +#define TFFS_ALLOW_UNFORMATTED + + +/* + * allow yielding CPU during flash write/erase operations + */ +#define TFFS_USE_SLEEP + + +/* Number of sockets + * + * Defines the maximum number of supported physical DiskOnChip devices. + * + * The actual number of sockets depends on which socket controllers are + * actually registered and the number of physical devices in the system. + */ +#define FL_SOCKETS 1 + + +/* Number of volumes + * + * Defines the maximum number of supported Disk (BDTL) partitions. + * + * The actual number of drives depends on which socket controllers are + * actually registered, the amount of devices in the system and the + * flash format placed on each device. + */ +#define FL_VOLUMES (14 * FL_SOCKETS) + + +/* Environment Variables + * + * Enable environment variables control of the TrueFFS features. + * + */ +#define FL_ENVIRONMENT_VARS + + +/* #define DOCH_ACCESS_LAYER_NOR */ +/* #define DOCH_ACCESS_LAYER_SPI */ + + +/* If you are using two cascaded DiskOnChip H3 devices, uncomment + * line below; otherwise keep it commented out. + */ +#define ATA_MAX_NUM_OF_DEVICES 2 /* only when using casacded devices */ + + +/* Forces the device into the deep power down mode after every driver operation */ +/* Compile the auto DPD code + * + * TrueFFS supports a mode, where TrueFFS automatically enters and exit DPD + * after every operation. + * + * The compilation bellow compiles that code. Note that it's operation is + * also under the affect of the dedicated environment variable. + */ +#define FL_BD_AUTO_DPD_MODE +#define FL_DEFAULT_BD_DPD_MODE(socket) tffs_auto_dpd +extern int tffs_auto_dpd; + + +/* Upon completion of every read/write access, DiskOnChip H3 devices + * immediately switch from the normal mode into the idle mode, and stay + * in the idle mode for 'DOCH_DPD_DEFAULT_DPD_TIMEOUT' milliseconds before + * switching into deep-power-down mode. + */ +#define DOCH_DPD_DEFAULT_DPD_TIMEOUT tffs_dpd_timeout +extern int tffs_dpd_timeout; + + +/* + * Remove all flash write functionalities from the code. + * + * When this option is selected, only API functions that do not involve write + * operations to the media can be called. + * + * This option can be used to create read-only applications with low RAM/ROM + * requirements. + */ +/* #define TFFS_RO */ +#ifdef TFFS_RO +# define FL_READ_ONLY +#endif + +/* IO Controll Interface + * + * Support standard IOCTL interface. + * + */ +#define FL_IOCTL_INTERFACE + + +#ifdef FL_IOCTL_INTERFACE + +/* Low level operations + * + * Uncomment the following line if you want to do low level operations + * (i.e. read from a physical address, write to a physical address, + * erase a unit according to its physical unit number, OTP and unique ID + * operations. + */ +# define FL_LOW_LEVEL + +/* Flash Formatting (Block device format) + * + * Uncomment the following line if you need to prepare a virgin DiskOnChip + * for work or in case you want to re-partition your existing device. + * + * This routine compiles the following 3 API routines: + * flFlashFormat(), flEraseBD() and flUnformat() + */ + +# ifndef TFFS_RO +# define FL_FORMAT_VOLUME +# endif + +/* H/W OTP + * + * Enable H/W One Time Programing capability including unique ID + * + */ +# define HW_OTP + +#endif /* FL_IOCTL_INTERFACE */ + + +/* Application exit + * + * If the FLite application ever exits, it needs to call flEXit before + * exiting. Uncomment the following line to enable this. + */ +#define FL_EXIT + + +/* H/W Protection + * + * Enable H/W protection of the device. + * + */ +#define HW_PROTECTION + + +/* Compile the code for reading after write + * + * Compiles the code and buffers for reading after every write operation + * This mode is used for debugging when you are still debugging the platform's + * H/W. + */ +#define FL_VERIFY_WRITE + + +/* Verify entire volume + * + * Compile the flVerifyVolume() routine - this routine scans the entire disk + * partition for power failures symptoms and correct them while initializing + * the TL cache. + * + */ +/* #define VERIFY_VOLUME */ + + +#ifdef FL_IOCTL_INTERFACE + +/* Binary Partition + * + * Enables access to the Binary partition. + * + */ +# define BDK_ACCESS + +#endif + + +#ifdef BDK_ACCESS + +/* Number of Binary partitions on the DiskOnChip. + * + * Defines Maximum Number of Binary partitions on the DiskOnChip. + * The actual number of partitions depends on the format placed + * on each device. + */ +# define FL_BINARY_PARTITIONS (3 * FL_SOCKETS) + +#endif /* BDK_ACCESS */ + + +/* Remove runtime controll over memory access routines + * + * If defined memory access routines will be set at compile time using + * dedicated defintions in flsystem.h + * Note : when compile time customization is chosen, you must sepcify + * the bus width even when working with DiskOnChip Millennium Plus. + * Refer to Trueffs manual for more infromation. + */ +/* #define FL_NO_USE_FUNC */ + + +/* + * Removes the code used for writing and reading the IPL code. + * + */ +#ifndef FL_IOCTL_INTERFACE +# define NO_IPL_CODE +#endif + + +/* Little-endian/big-endian + * + * FAT and translation layer structures use the little-endian (Intel) + * format for integers. + * If your machine uses the big-endian (Motorola) format, uncomment the + * following line. + * Note that even on big-endian machines you may omit the BIG_ENDIAN + * definition for smaller code size and better performance, but your media + * will not be compatible with standard FAT and FTL. + */ +/* #define FL_BIG_ENDIAN */ + + +/* #define FL_NO_INIT_MMU_PAGES */ + + +/* Compile the extended Disk information routine + * + * TrueFFS 6.0 and up provide an extended information routine for internal + * M-Systems utilities named flGetExtendedDiskInfo(). + * To compile its code define + */ +#define FL_EXTENDED_DISK_INFO + + +/* #define FL_NO_QUICK_MOUNT_FEATURE */ + + +/* Disable the automatic argument check + * + * You can remove code and even slightly improve the overall performance by + * allowing TrueFFS to skip its internal argument check by defining + * + */ +/* #define FL_SKIP_ARGS_CHECK */ + + +/* Absolute read & write + * + * Uncomment the following line if you want to be able to read & write + * sectors by absolute sector number (i.e. without regard to files and + * directories). + */ +#define FL_ABS_READ_WRITE + + +/* + * Include code related to DiskOnChip H3 burst mode + */ +#define DOCH_USE_BURST_MODE_READ +/* #define DOCH_USE_BURST_MODE_WRITE */ + +# if defined(DOCH_USE_BURST_MODE_READ) || defined(DOCH_USE_BURST_MODE_WRITE) + +# define BURST_LENGTH tffs_burst_length +# define BURST_LATENCY tffs_burst_latency +# define BURST_HOLD tffs_burst_hold +# define BURST_WAIT_STATE tffs_burst_ws + +# ifdef DOCH_USE_BURST_MODE_READ +# define FL_USE_BURST_MODE_READ +# endif + +# ifdef DOCH_USE_BURST_MODE_WRITE +# define FL_USE_BURST_MODE_WRITE +# endif + + extern int tffs_burst_length, tffs_burst_latency, tffs_burst_hold, tffs_burst_ws; + extern int tffs_burst_enabled; + +# endif /* DOCH_USE_BURST_MODE_READ || DOCH_USE_BURST_MODE_WRITE */ + + +extern unsigned int profiling[]; + + +#endif /* FLCUSTOM_H */ diff -urN linux-2.6.30.4-orig/drivers/block/tffs/flioctl.c linux-2.6.30.4/drivers/block/tffs/flioctl.c --- linux-2.6.30.4-orig/drivers/block/tffs/flioctl.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/flioctl.c 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,612 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ + +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/3/bddoc/src/flioctl.c-arc $ + * + * Rev 1.12 Oct 22 2007 11:34:52 einat.avidan + * update copyrights header + * + * Rev 1.11 Feb 28 2007 09:58:42 einat.avidan + * No change + * + * Rev 1.10.1.1 Oct 29 2006 14:23:46 Yaniv.Iarovici + * Update 'FL_IOCTL_PASS_THROUGH' structures. + * + * Rev 1.10.1.0 Oct 22 2006 14:53:52 yaniv.iarovici + * Changed protectionType from FLByte to FLWord in flProtectionOutput stucture. + * + * Rev 1.10 Oct 09 2006 14:05:34 yaniv.iarovici + * Removed #ifndef FL_DO_NOT_SUPPORT_H3 + * + * Rev 1.9 Oct 05 2006 11:00:56 yaniv.iarovici + * Fixed support for FL_IOCTL_PASS_THROUGH. + * + * Rev 1.8 Sep 11 2006 13:45:22 yaniv.iarovici + * Legal header added + * + * Rev 1.7 Aug 15 2006 09:32:32 Polina.Marimont + * IPL protection inside + * + * Rev 1.6 Aug 09 2006 16:52:50 Polina.Marimont + * initial for DOC Driver 1.0 + */ + +#include "flbase.h" +#include "blockdev.h" +#include "flioctl.h" +#ifdef BDK_ACCESS +#endif + +#ifdef FL_IOCTL_INTERFACE + +/*----------------------------------------------------------------------*/ +/* f l I O c t l */ +/* */ +/* The entry point for all TrueFFS extended functions. */ +/* */ +/* Note: This interface is common to all TrueFFS based drivers. However */ +/* since you can access TrueFFS diretly (without the driver) you */ +/* can also call the extended routines explicitly. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irData : Pointer to flIOctlRecord record see flioclt.h */ +/* irFlags : Opcode of the specific extended function. */ +/* See flioctl.h for the complete opcode list. */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ + +TFFS_DLL_API FLStatus NAMING_CONVENTION bdIOctl(IOreq FAR2 *ioreq1) +{ + IOreq ioreq2; + void FAR1 *inputRecord; + void FAR1 *outputRecord; + + inputRecord = ((flIOctlRecord FAR1 *)(ioreq1->irData))->inputRecord; + outputRecord = ((flIOctlRecord FAR1 *)(ioreq1->irData))->outputRecord; + ioreq2.irHandle = ioreq1->irHandle; + + switch (ioreq1->irFlags) { + case FL_IOCTL_GET_INFO: + { + flDiskInfoOutput FAR1 *outputRec = (flDiskInfoOutput FAR1 *)outputRecord; + + ioreq2.irData = &(outputRec->info); + outputRec->status = flVolumeInfo(&ioreq2); + return outputRec->status; + } +#ifndef FL_READ_ONLY + + case FL_IOCTL_DEFRAGMENT: + { + flDefragInput FAR1 *inputRec = (flDefragInput FAR1 *)inputRecord; + flDefragOutput FAR1 *outputRec = (flDefragOutput FAR1 *)outputRecord; + + ioreq2.irLength = inputRec->requiredNoOfSectors; + outputRec->status = flDefragmentVolume(&ioreq2); + outputRec->actualNoOfSectors = ioreq2.irLength; + return outputRec->status; + } + +#ifdef FL_FORMAT_VOLUME + + case FL_IOCTL_FLASH_FORMAT: + { + flFlashFormatInput FAR1 *inputRec = (flFlashFormatInput FAR1 *)inputRecord; + flOutputStatusRecord FAR1 *outputRec = (flOutputStatusRecord FAR1 *)outputRecord; + + ioreq2.irLength = inputRec->sdwNoOfKeeps; + ioreq2.irFlags = inputRec->dwFormatFlags; + ioreq2.irData = (void FAR1 *)inputRec->fpPtr; + outputRec->status = flFlashFormat(&ioreq2); + return outputRec->status; + } + case FL_IOCTL_ERASE_BD: + { + flEraseBDInput FAR1 *inputRec = (flEraseBDInput FAR1 *)inputRecord; + flOutputStatusRecord FAR1 *outputRec = (flOutputStatusRecord FAR1 *)outputRecord; + + ioreq2.irPath = NULL; /* Progress callback */ + ioreq2.irFlags = inputRec->dwFlags; + outputRec->status = flEraseBD(&ioreq2); + return outputRec->status; + } + case FL_IOCTL_FLASH_UNFORMAT: + { + flFlashUnformatInput FAR1 *inputRec = (flFlashUnformatInput FAR1 *)inputRecord; + flOutputStatusRecord FAR1 *outputRec = (flOutputStatusRecord FAR1 *)outputRecord; + + ioreq2.irPath = NULL; /* Progress callback */ + ioreq2.irFlags = inputRec->dwFlags; + outputRec->status = flUnformat(&ioreq2); + return outputRec->status; + } + +#endif /* FL_FORMAT_VOLUME */ +#endif /* FL_READ_ONLY */ + + case FL_IOCTL_MOUNT_VOLUME: + { + flMountInput FAR1 *inputRec = (flMountInput FAR1 *)inputRecord; + flOutputStatusRecord FAR1 *outputRec = (flOutputStatusRecord FAR1 *)outputRecord; + + if (inputRec->type == FL_DISMOUNT) + outputRec->status = flDismountVolume(&ioreq2); + else + outputRec->status = flAbsMountVolume(&ioreq2); + return outputRec->status; + } +#ifdef BDK_ACCESS + case FL_IOCTL_BDK_OPERATION: + { + flBDKOperationInput FAR1 *inputRec = (flBDKOperationInput FAR1 *)inputRecord; + flOutputStatusRecord FAR1 *outputRec = (flOutputStatusRecord FAR1 *)outputRecord; + + ioreq2.irData = &(inputRec->bdkStruct); + switch(inputRec->type) { + case BDK_INIT_READ: + outputRec->status = bdkReadInit(&ioreq2); + break; + case BDK_READ: + outputRec->status = bdkReadBlock(&ioreq2); + break; + case BDK_GET_INFO: + outputRec->status = bdkPartitionInfo(&ioreq2); + break; +#ifndef FL_READ_ONLY + case BDK_INIT_WRITE: + outputRec->status = bdkWriteInit(&ioreq2); + break; + case BDK_WRITE: + outputRec->status = bdkWriteBlock(&ioreq2); + break; + case BDK_ERASE: + outputRec->status = bdkErase(&ioreq2); + break; + case BDK_CREATE: + outputRec->status = bdkCreate(&ioreq2); + break; +#endif /* FL_READ_ONLY */ + default: + outputRec->status = flBadParameter; + break; + } + return outputRec->status; + } +#endif /* BDK_ACCESS */ +#ifdef HW_PROTECTION +#ifdef BDK_ACCESS + case FL_IOCTL_BINARY_HW_PROTECTION: + { + flProtectionInput FAR1 *inputRec = (flProtectionInput FAR1 *)inputRecord; + flProtectionOutput FAR1 *outputRec = (flProtectionOutput FAR1 *)outputRecord; + + switch(inputRec->type) + { + case PROTECTION_INSERT_KEY: + ioreq2.irData = inputRec->key; + outputRec->status = bdkInsertProtectionKey(&ioreq2); + break; + case PROTECTION_REMOVE_KEY: + outputRec->status = bdkRemoveProtectionKey(&ioreq2); + break; + case PROTECTION_GET_TYPE: + outputRec->status = bdkIdentifyProtection(&ioreq2); + outputRec->protectionType = (FLWord)ioreq2.irFlags; + break; + case PROTECTION_DISABLE_LOCK: + ioreq2.irFlags = 0; + outputRec->status = bdkHardwareProtectionLock(&ioreq2); + break; + case PROTECTION_ENABLE_LOCK: + ioreq2.irFlags = LOCK_ENABLED; + outputRec->status = bdkHardwareProtectionLock(&ioreq2); + break; + case PROTECTION_CHANGE_KEY: + ioreq2.irData = inputRec->key; + outputRec->status = bdkChangeProtectionKey(&ioreq2); + break; + case PROTECTION_CHANGE_TYPE: + ioreq2.irFlags = inputRec->protectionType; + outputRec->status = bdkChangeProtectionType(&ioreq2); + break; + default: + outputRec->status = flBadParameter; + break; + } + return outputRec->status; + } +#endif /* BDK_ACCESS */ + case FL_IOCTL_BDTL_HW_PROTECTION: + { + flProtectionInput FAR1 *inputRec = (flProtectionInput FAR1 *)inputRecord; + flProtectionOutput FAR1 *outputRec = (flProtectionOutput FAR1 *)outputRecord; + + switch(inputRec->type) + { + case PROTECTION_INSERT_KEY: + ioreq2.irData = inputRec->key; + outputRec->status = flInsertProtectionKey(&ioreq2); + break; + case PROTECTION_REMOVE_KEY: + outputRec->status = flRemoveProtectionKey(&ioreq2); + break; + case PROTECTION_GET_TYPE: + outputRec->status = flIdentifyProtection(&ioreq2); + outputRec->protectionType = (FLWord)ioreq2.irFlags; + break; + case PROTECTION_DISABLE_LOCK: + ioreq2.irFlags = 0; + outputRec->status = flHardwareProtectionLock(&ioreq2); + break; + case PROTECTION_ENABLE_LOCK: + ioreq2.irFlags = LOCK_ENABLED; + outputRec->status = flHardwareProtectionLock(&ioreq2); + break; + case PROTECTION_CHANGE_KEY: + ioreq2.irData = inputRec->key; + outputRec->status = flChangeProtectionKey(&ioreq2); + break; + case PROTECTION_CHANGE_TYPE: + ioreq2.irFlags = inputRec->protectionType; + outputRec->status = flChangeProtectionType(&ioreq2); + break; + case PROTECTION_APPLY_STICKY: + outputRec->status = flApplyStickyLock(&ioreq2); + break; + default: + outputRec->status = flBadParameter; + break; + } + return outputRec->status; + } + case FL_IOCTL_IPL_HW_PROTECTION: + { + flProtectionInput FAR1 *inputRec = (flProtectionInput FAR1 *)inputRecord; + flProtectionOutput FAR1 *outputRec = (flProtectionOutput FAR1 *)outputRecord; + + switch(inputRec->type) + { + case PROTECTION_INSERT_KEY: + ioreq2.irData = inputRec->key; + outputRec->status = flIplInsertProtectionKey(&ioreq2); + break; + case PROTECTION_REMOVE_KEY: + outputRec->status = flIplRemoveProtectionKey(&ioreq2); + break; + case PROTECTION_GET_TYPE: + outputRec->status = flIplIdentifyProtection(&ioreq2); + outputRec->protectionType = (FLWord)ioreq2.irFlags; + break; + case PROTECTION_CHANGE_KEY: + ioreq2.irData = inputRec->key; + outputRec->status = flIplChangeProtectionKey(&ioreq2); + break; + case PROTECTION_CHANGE_TYPE: + ioreq2.irFlags = inputRec->protectionType; + outputRec->status = flIplChangeProtectionType(&ioreq2); + break; + default: + outputRec->status = flBadParameter; + break; + } + return outputRec->status; + } +#endif /* HW_PROTECTION */ +#ifdef HW_OTP + case FL_IOCTL_OTP: + { + flOtpInput FAR1 *inputRec = (flOtpInput FAR1 *)inputRecord; + flOutputStatusRecord FAR1 *outputRec = (flOutputStatusRecord FAR1 *)outputRecord; + + switch(inputRec->type) + { + case OTP_SIZE: + outputRec->status = flOTPSize(&ioreq2); + inputRec->lockedFlag = (FLByte)ioreq2.irFlags; + inputRec->length = ioreq2.irCount ; + inputRec->usedSize = ioreq2.irLength ; + break; + case OTP_READ: + ioreq2.irData = inputRec->buffer; /* user buffer */ + ioreq2.irCount = inputRec->usedSize; /* offset */ + ioreq2.irLength = inputRec->length; /* size to read */ + outputRec->status = flOTPRead(&ioreq2); + break; + case OTP_WRITE_LOCK: + ioreq2.irData = inputRec->buffer; /* user buffer */ + ioreq2.irLength = inputRec->length; /* size to read */ + outputRec->status = flOTPWriteAndLock(&ioreq2); + break; + default: + outputRec->status = flBadParameter; + break; + } + return outputRec->status; + } + + case FL_IOCTL_MCOTP: + { + flMCOtpInput FAR1 *inputRec = (flMCOtpInput FAR1 *)inputRecord; + flOutputStatusRecord FAR1 *outputRec = (flOutputStatusRecord FAR1 *)outputRecord; + + switch(inputRec->type) + { + case MCOTP_SIZE: + outputRec->status = flMCOTPSize(&ioreq2); + inputRec->lockedFlag = (FLByte)ioreq2.irFlags; + inputRec->length = ioreq2.irCount ; + inputRec->usedSize = ioreq2.irLength ; + break; + case MCOTP_READ: + ioreq2.irData = inputRec->buffer; /* user buffer */ + ioreq2.irCount = inputRec->wPageNo; /* offset */ + outputRec->status = flMCOTPRead(&ioreq2); + break; + case MCOTP_WRITE_LOCK: + ioreq2.irData = inputRec->buffer; /* user buffer */ + ioreq2.irCount = inputRec->wPageNo; /* offset */ + outputRec->status = flMCOTPWriteAndLock(&ioreq2); + break; + default: + outputRec->status = flBadParameter; + break; + } + return outputRec->status; + } + + case FL_IOCTL_CUSTOMER_ID: + { + flCustomerIdOutput FAR1 *outputRec = (flCustomerIdOutput FAR1 *)outputRecord; + + ioreq2.irData = outputRec->id; + outputRec->status = flGetCustomerID(&ioreq2); + return outputRec->status; + } + + case FL_IOCTL_UNIQUE_ID: + { + flUniqueIdOutput FAR1 *outputRec = (flUniqueIdOutput FAR1 *)outputRecord; + + ioreq2.irData = outputRec->id; + outputRec->status = flGetUniqueID(&ioreq2); + return outputRec->status; + } +#endif /* HW_OTP */ + + case FL_IOCTL_NUMBER_OF_PARTITIONS: + { + flCountPartitionsOutput FAR1 *outputRec = (flCountPartitionsOutput FAR1 *)outputRecord; + + outputRec->status = flCountVolumes(&ioreq2); + outputRec->noOfPartitions = (FLByte) ioreq2.irFlags; + return outputRec->status; + } + +#ifdef FL_LOW_LEVEL + + case FL_IOCTL_DEEP_POWER_DOWN_MODE: + { + flPowerDownInput FAR1 *inputRec = (flPowerDownInput FAR1 *)inputRecord; + flOutputStatusRecord FAR1 *outputRec = (flOutputStatusRecord FAR1 *)outputRecord; + ioreq2.irFlags = inputRec->state; + outputRec->status = flDeepPowerDownMode(&ioreq2); + return outputRec->status; + } + +#endif /* FL_LOW_LEVEL */ +#ifdef FL_ABS_READ_WRITE +#ifndef FL_READ_ONLY + case FL_IOCTL_DELETE_SECTORS: + { + flDeleteSectorsInput FAR1 *inputRec = (flDeleteSectorsInput FAR1 *)inputRecord; + flOutputStatusRecord FAR1 *outputRec = (flOutputStatusRecord FAR1 *)outputRecord; + + ioreq2.irSectorNo = inputRec->firstSector; + ioreq2.irSectorCount = inputRec->numberOfSectors; + outputRec->status = flAbsDelete(&ioreq2); + return outputRec->status; + } +#endif /* FL_READ_ONLY */ + + case FL_IOCTL_READ_SECTORS: + { + flReadWriteInput FAR1 *inputRec = (flReadWriteInput FAR1 *)inputRecord; + flReadWriteOutput FAR1 *outputRec = (flReadWriteOutput FAR1 *)outputRecord; + + ioreq2.irSectorNo = inputRec->firstSector; + ioreq2.irSectorCount = inputRec->numberOfSectors; + ioreq2.irData = inputRec->buf; + outputRec->status = flAbsRead(&ioreq2); + outputRec->numberOfSectors = ioreq2.irSectorCount; + return outputRec->status; + } +#ifndef FL_READ_ONLY + + case FL_IOCTL_WRITE_SECTORS: + { + flReadWriteInput FAR1 *inputRec = (flReadWriteInput FAR1 *)inputRecord; + flReadWriteOutput FAR1 *outputRec = (flReadWriteOutput FAR1 *)outputRecord; + + ioreq2.irSectorNo = inputRec->firstSector; + ioreq2.irSectorCount = inputRec->numberOfSectors; + ioreq2.irData = inputRec->buf; + outputRec->status = flAbsWrite(&ioreq2); + outputRec->numberOfSectors = ioreq2.irSectorCount; + return outputRec->status; + } +#endif /* FL_READ_ONLY */ +#endif /* FL_ABS_READ_WRITE */ + +#ifdef FL_ENVIRONMENT_VARS + case FL_IOCTL_EXTENDED_ENVIRONMENT_VARIABLES: + { + flExtendedEnvVarsInput FAR1 *inputRec = (flExtendedEnvVarsInput FAR1 *)inputRecord; + flExtendedEnvVarsOutput FAR1 *outputRec = (flExtendedEnvVarsOutput FAR1 *)outputRecord; + + switch(inputRec->flags) + { + case FL_APPLY_TO_ALL: + outputRec->status = flSetEnvAll(inputRec->varName, + inputRec->varValue,&(outputRec->prevValue)); + break; + case FL_APPLY_TO_SOCKET: + outputRec->status = flSetEnvSocket(inputRec->varName, + FL_GET_SOCKET_FROM_HANDLE((&ioreq2)), + inputRec->varValue,&(outputRec->prevValue)); + break; + case FL_APPLY_TO_VOLUME: + outputRec->status = flSetEnvVolume(inputRec->varName, + FL_GET_SOCKET_FROM_HANDLE((&ioreq2)), + FL_GET_FLASH_PARTITION_FROM_HANDLE((&ioreq2)), + inputRec->varValue,&(outputRec->prevValue)); + break; + default: + DBG_PRINT_ERR(FLZONE_IOCTL,"ERROR - Unrecognized environment variable function flag.\r\n"); + outputRec->status = flFeatureNotSupported; + } + return outputRec->status; + } +#endif /* FL_ENVIRONMENT_VARS */ + +#ifndef FL_NO_USE_FUNC + case FL_IOCTL_SET_ACCESS_ROUTINE: + { + flSetMemoryAccessInput FAR1 *inputRec = (flSetMemoryAccessInput FAR1 *)inputRecord; + flOutputStatusRecord FAR1 *outputRec = (flOutputStatusRecord FAR1 *)outputRecord; + + outputRec->status = flSetDocBusRoutine(FL_GET_SOCKET_FROM_HANDLE((&ioreq2)), + inputRec->structPtr); + return outputRec->status; + } + case FL_IOCTL_GET_ACCESS_ROUTINE: + { + flGetMemoryAccessOutput FAR1 *outputRec = (flGetMemoryAccessOutput FAR1 *)outputRecord; + + outputRec->status = flGetDocBusRoutine(FL_GET_SOCKET_FROM_HANDLE((&ioreq2)), + outputRec->structPtr); + return outputRec->status; + } +#endif /* FL_NO_USE_FUNC */ + +#ifdef VERIFY_VOLUME + case FL_IOCTL_VERIFY_VOLUME: + { + flVerifyVolumeInput FAR1 *inputRec = (flVerifyVolumeInput FAR1 *)inputRecord; + flVerifyVolumeOutput FAR1 *outputRec = (flVerifyVolumeOutput FAR1 *)outputRecord; + + ioreq2.irLength = (FLSDword)inputRec->flags; + ioreq2.irData = outputRec->callBack; + outputRec->status = flVerifyVolume(&ioreq2); + return outputRec->status; + } +#endif /* VERIFY_VOLUME */ + +#ifndef NO_IPL_CODE + case FL_IOCTL_WRITE_IPL: + { + flIPLInput FAR1 *inputRec = (flIPLInput FAR1 *)inputRecord; + flOutputStatusRecord FAR1 *outputRec = (flOutputStatusRecord FAR1 *)outputRecord; + ioreq2.irData = inputRec->bBufPtr; + ioreq2.irLength = inputRec->sdwLength; + ioreq2.irCount = inputRec->sdwOffset; + ioreq2.irFlags = inputRec->dwFlags; + outputRec->status = flWriteIPL(&ioreq2); + return outputRec->status; + } +#endif /* NO_IPL_CODE */ + +#ifndef FL_NO_QUICK_MOUNT_FEATURE + case FL_IOCTL_IS_QUICK_MOUNT_VALID: + { + flGetQuickMountOutput FAR1 *outputRec = (flGetQuickMountOutput FAR1 *)outputRecord; + outputRec->status = flGetQuickMountStatus(&ioreq2); + outputRec->mode = (FLByte)ioreq2.irFlags; + return outputRec->status; + } +#ifndef FL_READ_ONLY + case FL_IOCTL_WRITE_QUICK_MOUNT_INFO: + { + flOutputStatusRecord FAR1 *outputRec = (flOutputStatusRecord FAR1 *)outputRecord; + outputRec->status = flWriteQuickMountInfo(&ioreq2); + return outputRec->status; + } + + case FL_IOCTL_CLEAR_QUICK_MOUNT_INFO: + { + flOutputStatusRecord FAR1 *outputRec = (flOutputStatusRecord FAR1 *)outputRecord; + outputRec->status = flClearQuickMountInfo(&ioreq2); + return outputRec->status; + } +#endif /* FL_READ_ONLY */ +#endif /* FL_NO_QUICK_MOUNT_FEATURE */ + + case FL_IOCTL_PASS_THROUGH: + { + flAtaPassthroughInput* ptIN = (flAtaPassthroughInput*)inputRecord; + flAtaPassthroughOutput* ptOUT = (flAtaPassthroughOutput*)outputRecord; + + ioreq2.irData = ptIN->userBuff; + ioreq2.irLength = ptIN->secNum; + ioreq2.irCount = ( + (ptIN->passThruOP) | + (ptIN->useInterrupt<<2) | + (ptIN->multSectorFrame<<4) ); + ioreq2.irPath = ptIN->in_regs; + + ptOUT->status = flDochPassThrough(&ioreq2); + + tffscpy(ptOUT->out_regs, ptIN->in_regs, sizeof(DOCH_Registers)); + return ptOUT->status; + } + + default: + return flBadParameter; + } +} + +#endif /* FL_IOCTL_INTERFACE */ diff -urN linux-2.6.30.4-orig/drivers/block/tffs/flioctl.h linux-2.6.30.4/drivers/block/tffs/flioctl.h --- linux-2.6.30.4-orig/drivers/block/tffs/flioctl.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/flioctl.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,490 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ + +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/3/common/flioctl.h-arc $ + * + * Rev 1.17 Oct 22 2007 11:34:52 einat.avidan + * update copyrights header + * + * Rev 1.16 Jul 02 2007 11:43:46 einat.avidan + * bug fix: SCR2966 : removed flags which are not in use + * FL_IPL_DOWNLOAD + * FL_IPL_ALERNATE_MAP + * FL_USING_BUFFERS + * FL_IPL_NO_ADDRESS_SHIFT_MODE + * + * Rev 1.15 Feb 28 2007 09:53:48 einat.avidan + * No change + * + * Rev 1.14.1.1 Oct 29 2006 14:23:46 Yaniv.Iarovici + * Update 'FL_IOCTL_PASS_THROUGH' structures. + * + * Rev 1.14.1.0 Oct 22 2006 14:53:58 yaniv.iarovici + * Changed protectionType from FLByte to FLWord in flProtectionOutput stucture. + * + * Rev 1.14 Oct 09 2006 14:05:38 yaniv.iarovici + * Removed #ifndef FL_DO_NOT_SUPPORT_H3 + * + * Rev 1.13 Oct 05 2006 11:01:06 yaniv.iarovici + * Fixed support for FL_IOCTL_PASS_THROUGH. + * + * Rev 1.12 Sep 11 2006 13:45:22 yaniv.iarovici + * Legal header added + * + * Rev 1.11 Aug 16 2006 08:47:20 Yaniv.Iarovici + * Encapsulate BDK related defines under '#ifdef BDK_ACCESS'. + * + * Rev 1.9 Aug 09 2006 16:52:50 Polina.Marimont + * initial for DOC Driver 1.0 + */ + +#ifndef FLIOCTL_H +#define FLIOCTL_H + +#include "flsystem.h" +#include "flstruct.h" +#include "_dochapi.h" + + +/* In every call to flIOctl function, the irFlags field in the structure +IOreq should hold one of the following: */ +typedef enum{FL_IOCTL_GET_INFO = FL_IOCTL_START, + FL_IOCTL_DEFRAGMENT, + FL_IOCTL_NO_LONGER_SUPPORTED_0, /* FL_IOCTL_WRITE_PROTECT */ + FL_IOCTL_MOUNT_VOLUME, + FL_IOCTL_NO_LONGER_SUPPORTED_1, /* FL_IOCTL_FORMAT_VOLUME */ +#ifdef BDK_ACCESS + FL_IOCTL_BDK_OPERATION, +#else /*BDK_ACCESS*/ + FL_IOCTL_RESERVED1, +#endif /*BDK_ACCESS*/ + FL_IOCTL_DELETE_SECTORS, + FL_IOCTL_READ_SECTORS, + FL_IOCTL_WRITE_SECTORS, + FL_IOCTL_NO_LONGER_SUPPORTED_2, /* FL_IOCTL_FORMAT_PHYSICAL_DRIVE */ + FL_IOCTL_NO_LONGER_SUPPORTED_3, /* FL_IOCTL_FORMAT_LOGICAL_DRIVE */ + FL_IOCTL_BDTL_HW_PROTECTION, +#ifdef BDK_ACCESS + FL_IOCTL_BINARY_HW_PROTECTION, +#else /*BDK_ACCESS*/ + FL_IOCTL_RESERVED2, +#endif /*BDK_ACCESS*/ + FL_IOCTL_OTP, + FL_IOCTL_CUSTOMER_ID, + FL_IOCTL_UNIQUE_ID, + FL_IOCTL_NUMBER_OF_PARTITIONS, + FL_IOCTL_NO_LONGER_SUPPORTED_4, /* FL_IOCTL_INQUIRE_CAPABILITIES */ + FL_IOCTL_NO_LONGER_SUPPORTED_5, /* FL_IOCTL_SET_ENVIRONMENT_VARIABLES */ + FL_IOCTL_NO_LONGER_SUPPORTED_6, /* FL_IOCTL_PLACE_EXB_BY_BUFFER */ + FL_IOCTL_NO_LONGER_SUPPORTED_7, /* FL_IOCTL_WRITE_IPL */ + FL_IOCTL_DEEP_POWER_DOWN_MODE, + FL_IOCTL_EXTENDED_ENVIRONMENT_VARIABLES, + FL_IOCTL_VERIFY_VOLUME, + FL_IOCTL_SET_ACCESS_ROUTINE, + FL_IOCTL_GET_ACCESS_ROUTINE, + FL_IOCTL_NO_LONGER_SUPPORTED_8, /* FL_IOCTL_EXTENDED_WRITE_IPL */ + FL_IOCTL_NO_LONGER_SUPPORTED_9, /* FL_IOCTL_OPEN_TRANSACTION */ + FL_IOCTL_NO_LONGER_SUPPORTED_10, /* FL_IOCTL_COMMIT_TRANSACTION */ + FL_IOCTL_NO_LONGER_SUPPORTED_11, /* FL_IOCTL_IS_VOLUME_RUGGEDIZED */ + FL_IOCTL_IS_QUICK_MOUNT_VALID, + FL_IOCTL_WRITE_QUICK_MOUNT_INFO, + FL_IOCTL_CLEAR_QUICK_MOUNT_INFO, + FL_IOCTL_NO_LONGER_SUPPORTED_12, /* FL_IOCTL_COMPLETE_OPERATION */ + FL_IOCTL_FLASH_FORMAT, /* Replacing FL_IOCTL_FORMAT_PHYSICAL_DRIVE */ + FL_IOCTL_ERASE_BD, /* Added in TrueFFS 6.3.0 */ + FL_IOCTL_FLASH_UNFORMAT, /* Added in TrueFFS 6.3.0 */ + FL_IOCTL_WRITE_IPL, /* Changed in TrueFFS 6.3.0 */ + FL_IOCTL_MCOTP, + FL_IOCTL_PASS_THROUGH, + FL_IOCTL_IPL_HW_PROTECTION +} flIOctlFunctionNo; + + +/* In every call to flIOctl function, the irData field in the structure +IOreq should point to the structure defined below. The fields +inputRecord and outputRecord should point to structures which are +specific to each IOctl function as defined in this file. */ +typedef struct { + void FAR1 *inputRecord; + void FAR1 *outputRecord; +} flIOctlRecord; + + +/* General output record that returns only status. */ +typedef struct { + FLStatus status; +} flOutputStatusRecord; + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +TFFS_DLL_API FLStatus NAMING_CONVENTION bdIOctl(IOreq FAR2 *); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#ifndef flIOctl +#define flIOctl bdIOctl +#endif + + +/* Input and output records for the different IOCTL functions: */ +/* =========================================================== */ + + +/*************************************************************************/ +/* Get disk information (FL_IOCTL_GET_INFO) */ +/* Input record: NULL */ +/* Output record: */ +typedef struct +{ + VolumeInfoRecord info; + FLStatus status; +} flDiskInfoOutput; +/* Output record: flOutputStatusRecord */ + +/*************************************************************************/ +/* Defragment volume (FL_IOCTL_DEFRAGMENT) */ +/* Input record: */ +typedef struct { + FLSDword requiredNoOfSectors; /* Minimum number of sectors to make */ + /* available. */ +} flDefragInput; +/* Outout record: */ +typedef struct { + FLSDword actualNoOfSectors; /* Actual number of sectors available */ + FLStatus status; +} flDefragOutput; + +/*************************************************************************/ +/* Mount volume (FL_IOCTL_MOUNT_VOLUME) */ +/* Input record: */ +typedef struct { + FLByte type; /* type of operation: FL_MOUNT\FL_DISMOUNT */ +} flMountInput; +#define FL_MOUNT 0 +#define FL_DISMOUNT 1 +/* Output record: flOutputStatusRecord */ + +/*************************************************************************/ +/* Delete logical sectors (FL_IOCTL_DELETE_SECTORS) */ +/* Input record: */ +typedef struct { + FLSDword firstSector; /* First logical sector to delete */ + FLSDword numberOfSectors; /* Number of sectors to delete */ +} flDeleteSectorsInput; +/* Output record: flOutputStatusRecord */ + +/*************************************************************************/ +/* Format flash device (FL_IOCTL_FLASH_FORMAT) */ +/* Input record: */ +typedef struct { + FLDword dwFormatFlags; /* type of format as defined in blockdev.h */ + FLSDword sdwNoOfKeeps; + FormatParams3 * fpPtr; /* Format parameters structure (defined in flformat.h) */ +} flFlashFormatInput; +/* Output record: flOutputStatusRecord */ + +/*************************************************************************/ +/* Erase existing disk partition (FL_IOCTL_ERASE_BD) */ +/* Input record: */ +typedef struct { + FLDword dwFlags; /* Reserved - Must be set to 0 */ +} flEraseBDInput; +/* Output record: flOutputStatusRecord */ + +/*************************************************************************/ +/* Format flash device (FL_IOCTL_FLASH_UNFORMAT) */ +/* Input record: */ +typedef struct { + FLDword dwFlags; /* Reserved - Must be set to 0 */ +} flFlashUnformatInput; +/* Output record: flOutputStatusRecord */ + +/*************************************************************************/ +/* BDK and BDTL protection operations: (FL_IOCTL_BINARY_HW_PROTECTION) */ +/* (FL_IOCTL_BDTL_HW_PROTECTION) */ +/* insert key \ remove key \ identify \ change key \ */ +/* change protection type \ change lock status */ +/* Input record: */ +typedef struct { + FLByte protectionType; /* Protection attributes. The following */ + /*attributes can be ored: PROTECTABLE, */ + /*READ_PROTECTED, WRITE_PROTECTED, LOCK_ENABLED*/ + /*CHANGEABLE_PROTECTION, OTW_PROTECTED, */ + FLByte key[8]; /* The new key to the change Key call */ + FLByte type; /* Operation type. available values are: */ + /*PROTECTION_INSERT_KEY, PROTECTION_REMOVE_KEY,*/ + /*PROTECTION_GET_TYPE, PROTECTION_DISABLE_LOCK,*/ + /*PROTECTION_ENABLE_LOCK, PROTECTION_CHANGE_KEY,*/ + /*PROTECTION_CHANGE_TYPE */ +} flProtectionInput; +#define PROTECTION_INSERT_KEY 0 +#define PROTECTION_REMOVE_KEY 1 +#define PROTECTION_GET_TYPE 2 +#define PROTECTION_DISABLE_LOCK 3 +#define PROTECTION_ENABLE_LOCK 4 +#define PROTECTION_CHANGE_KEY 5 +#define PROTECTION_CHANGE_TYPE 6 +#define PROTECTION_APPLY_STICKY 7 +/* Output record: */ +typedef struct { + FLWord protectionType; /* Protection attributes. The following */ + /*attributes can be ored: PROTECTABLE, */ + /*READ_PROTECTED, WRITE_PROTECTED, LOCK_ENABLED*/ + /*LOCK_ASSERTED, KEY_INSERTED, */ + /*CHANGEABLE_PROTECTION, OTW_PROTECTED, */ + /*STICKY_LOCK_ASSERTED */ + + FLStatus status; +} flProtectionOutput; + +/*************************************************************************/ +/* One Time Programing operations: (FL_IOCTL_OTP */ +/* OTP size \ OTP read \ OTP write and lock */ +/* Input record: */ +typedef struct { + FLDword length; /* Length to read\write\size */ + FLDword usedSize; /* The written size of the area \ Area offset */ + FLByte lockedFlag; /* The area condition LOCKED_OTP (flflash.h) */ + FLByte FAR1* buffer; /* pointer to user buffer */ + FLWord type; /* defined bellow */ +} flOtpInput; +#define OTP_SIZE 1 +#define OTP_READ 2 +#define OTP_WRITE_LOCK 3 +/* Output record: flOutputStatusRecord */ + +/*************************************************************************/ +/* One Time Programing operations: (FL_IOCTL_MCOTP */ +/* OTP size \ OTP read \ OTP write and lock */ +/* Input record: */ +typedef struct { + FLWord wPageNo ; /* Page to write */ + FLDword length; /* Length to read\write\size */ + FLDword usedSize; /* The written size of the area \ Area offset */ + FLByte lockedFlag; /* The area condition LOCKED_OTP (flflash.h) */ + FLByte FAR1* buffer; /* pointer to user buffer */ + FLWord type; /* defined bellow */ +} flMCOtpInput; + +#define MCOTP_SIZE 1 +#define MCOTP_READ 2 +#define MCOTP_WRITE_LOCK 3 +/* Output record: flOutputStatusRecord */ + +/*************************************************************************/ +/* Read customer ID (FL_IOCTL_CUSTOMER_ID) */ +/* Input record: NULL */ +/* Output record: */ +typedef struct { + FLByte id[4]; + FLStatus status; +} flCustomerIdOutput; + +/*************************************************************************/ +/* Read unique ID (FL_IOCTL_UNIQUE_ID) */ +/* Input record: NULL */ +/* Output record: */ +typedef struct { + FLByte id[16]; + FLStatus status; +} flUniqueIdOutput; + +/*************************************************************************/ +/* Read unique ID (FL_IOCTL_NUMBER_OF_PARTITIONS) */ +/* Input record: NULL */ +/* Output record: */ +typedef struct { + FLByte noOfPartitions; + FLStatus status; +} flCountPartitionsOutput; + +/*************************************************************************/ +/* Place the device into and out of the power down mode (FL_IOCTL_DEEP_POWER_DOWN_MODE) */ + +/* Input record: */ +typedef struct { + FLByte state; /* DEEP_POWER_DOWN - low power consumption */ + /* EXIT_DEEP_POWER_DOWN - regular power consumption */ +} flPowerDownInput; +/* Output record: flOutputStatusRecord */ + +#ifdef BDK_ACCESS +/*************************************************************************/ +/* BDK operations read\write\erase\create (FL_IOCTL_BDK_OPERATION) */ +/* Input record: */ +typedef struct { + FLByte type; /* type of operation. Available are: */ + /*BDK_INIT_READ, BDK_READ, BDK_INIT_WRITE, */ + /*BDK_WRITE, BDK_ERASE, BDK_CREATE, */ + /* BDK_GET_INFO */ + BDKStruct bdkStruct; /* parameters for BDK operations */ +} flBDKOperationInput; +#define BDK_INIT_READ 0 +#define BDK_READ 1 +#define BDK_INIT_WRITE 2 +#define BDK_WRITE 3 +#define BDK_ERASE 4 +#define BDK_CREATE 5 +#define BDK_GET_INFO 6 +/* Output record: flOutputStatusRecord */ +#endif /*BDK_ACCESS*/ + +/******************************************************************************/ +/* Set environment variables values (FL_IOCTL_EXTENDED_ENVIRONMENT_VARIABLES) */ +/* Input record: */ +typedef struct { + FLEnvVars varName; /* Enum describing the variable */ + FLDword varValue; /* New variable value */ + FLDword flags; /* FL_APPLY_TO_ALL - All socket and partitions */ + /* FL_APPLY_TO_SOCKET - All socket and partitions */ + /* FL_APPLY_TO_VOLUME - All socket and partitions */ +} flExtendedEnvVarsInput; +#define FL_APPLY_TO_ALL 1 +#define FL_APPLY_TO_SOCKET 2 +#define FL_APPLY_TO_VOLUME 3 +/* Output record: */ +typedef struct { + FLDword prevValue; /* The previous value of the variable */ + FLStatus status; +} flExtendedEnvVarsOutput; + +/******************************************************************************/ +/* Write IPL area for docPlus family (FL_IOCTL_WRITE_IPL) */ +/* Input record: */ +typedef struct { + FLByte FAR1* bBufPtr; /* IPL data buffer */ + FLDword dwFlags; /* IPL flags. Available are: FL_IPL_MODE_NORMAL, */ + /* FL_DOC_IPL_PAGED_RAM_MODE,FL_IPL_VIRTUAL_RAM_MODE*/ + /* FL_IPL_128K_WINDOW_MODE, FL_IPL_SWAP_BYTES_MODE*/ + FLSDword sdwLength; /* IPL length */ + FLSDword sdwOffset; /* IPL offset */ +} flIPLInput; +/* Output record: flOutputStatusRecord */ + +/******************************************************************************/ +/* Check quick mount validity (FL_IOCTL_IS_QUICK_MOUNT_VALID) */ +/* Input record: NULL */ +/* Output record: */ +typedef struct { + FLByte mode; /* Either FL_ON for valid and FL_OFF for not */ + FLStatus status; +} flGetQuickMountOutput; + +/******************************************************************************/ +/* Write quick mount data (FL_IOCTL_WRITE_QUICK_MOUNT_INFO) */ +/* Input record: NULL */ +/* Output record: flOutputStatusRecord */ + +/******************************************************************************/ +/* Clear quick mount data (FL_IOCTL_CLEAR_QUICK_MOUNT_INFO) */ +/* Input record: NULL */ +/* Output record: flOutputStatusRecord */ + +/*************************************************************************/ +/* read & write logical sectors (FL_IOCTL_READ_SECTORS & FL_IOCTL_WRITE_SECTORS) */ +/* Input record: */ +typedef struct { + FLSDword firstSector; /* first logical sector */ + FLSDword numberOfSectors; /* Number of sectors to read\write */ + FLByte FAR1 *buf; /* Data to read\write */ +} flReadWriteInput; +/* Output record: */ +typedef struct { + FLSDword numberOfSectors; /* Actual Number of sectors read\written */ + FLStatus status; +} flReadWriteOutput; + +/******************************************************************************/ +/* Check partition for power failures symptoms (FL_IOCTL_VERIFY_VOLUME) */ +/* Input record: NULL */ +typedef struct { + FLDword flags; /* Must be set to 0 */ +} flVerifyVolumeInput; +/* Output record: */ +typedef struct { + void FAR1* callBack; /* Must be set to null */ + FLStatus status; +} flVerifyVolumeOutput; + +/******************************************************************************/ +/* Plant user defined memory access routines (FL_IOCTL_SET_ACCESS_ROUTINE) */ +/* Input record: */ +typedef struct { + FLAccessStruct FAR1 * structPtr; /* Pointer memory access routine struct */ +} flSetMemoryAccessInput; +/* Output record: flOutputStatusRecord */ + +/******************************************************************************/ +/* Plant user defined memory access routines (FL_IOCTL_GET_ACCESS_ROUTINE) */ +/* Input record: NULL */ +/* Output record: */ +typedef struct { + FLAccessStruct FAR1 * structPtr; /* Pointer memory access routine struct */ + FLStatus status; +} flGetMemoryAccessOutput; + +/******************************************************************************/ +/* Perform ATA command using the pass-through mechanism (FL_IOCTL_PASS_THROUGH) */ +/* Input record: */ +typedef struct { + DOCH_PassThru_Op passThruOP; /*0 - No Data(CTRL), 1 - Data IN, 2 - Data OUT*/ + DOCH_PassThru_Int useInterrupt; /*0 - Do NOT use interrupt, 1- USE interrupt*/ + FLSDword multSectorFrame;/*DRQ size exponent (power of 2)*/ + DOCH_Registers* in_regs; /*ATA input registers*/ + FLSDword secNum; /*Number of sectors in user buffer*/ + void* userBuff; /* User buffer (for read\write) */ +} flAtaPassthroughInput; +/* Output record: */ +typedef struct { + DOCH_Registers* out_regs; /*ATA input registers*/ + FLStatus status; +} flAtaPassthroughOutput; + + +#endif /* FLIOCTL_H */ diff -urN linux-2.6.30.4-orig/drivers/block/tffs/flstdcmp.h linux-2.6.30.4/drivers/block/tffs/flstdcmp.h --- linux-2.6.30.4-orig/drivers/block/tffs/flstdcmp.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/flstdcmp.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,95 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ + +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/version 6.3-up/TrueFFS/src/flstdcmp.h-arc $ + * + * Rev 1.25 Oct 22 2007 11:34:54 einat.avidan + * update copyrights header + * + * Rev 1.24 Feb 28 2007 09:53:48 einat.avidan + * No change + * + * Rev 1.23.1.0 Oct 22 2006 14:54:06 yaniv.iarovici + * Changed flRegisterDOCH3SOC()return type to FLStatus. + * + * Rev 1.23 Oct 09 2006 14:05:48 yaniv.iarovici + * 1. Removed #ifndef FL_DO_NOT_SUPPORT_H3 + * 2. Removed legacy devices related code and definitions + * + * Rev 1.22 Sep 13 2006 10:30:46 yaniv.iarovici + * Fix compilation warnings + * + * Rev 1.21 Sep 11 2006 13:45:22 yaniv.iarovici + * Legal header added + * + * Rev 1.20 Aug 09 2006 16:52:50 Polina.Marimont + * initial for DOC Driver 1.0 + */ + +#ifndef FLSTDCOMP_H +#define FLSTDCOMP_H + +#include "doch_api.h" + +/************************************************************************/ +/* Registration routines for socket I/F supplied with TrueFFS */ +/************************************************************************/ + +FLStatus flRegisterDOCH3SOC(FLDword dwAddress); /* see TFFS_API.C */ + +/* DiskOnChip H3 Register Routine */ +FLStatus flRegisterDochParams(void); + +/* DiskOnChip H3 Access layer routine - not used in 7.x version */ +#ifdef DOCH_USE_FUNC +#define flRegisterDOCH_Hal_SPI() ((hal_init_spi(0) == 0) ? DOCH_OK : DOCH_GeneralFailure) +#define flRegisterDOCH_Hal_SIM() ((hal_init_sim(0) == 0) ? DOCH_OK : DOCH_GeneralFailure) +#define flRegisterDOCH_Hal_NOR() ((hal_init_nor(0) == 0) ? DOCH_OK : DOCH_GeneralFailure) +#else /*DOCH_USE_FUNC*/ +#define flRegisterDOCH_Hal_SPI() ((hal_init_spi_noFunc(0) == 0) ? DOCH_OK : DOCH_GeneralFailure) +#define flRegisterDOCH_Hal_SIM() ((hal_init_sim_noFunc(0) == 0) ? DOCH_OK : DOCH_GeneralFailure) +#define flRegisterDOCH_Hal_NOR() ((hal_init_nor_noFunc(0) == 0) ? DOCH_OK : DOCH_GeneralFailure) +#endif /*DOCH_USE_FUNC*/ + +#endif /* FLSTDCOMP_H */ diff -urN linux-2.6.30.4-orig/drivers/block/tffs/flstruct.h linux-2.6.30.4/drivers/block/tffs/flstruct.h --- linux-2.6.30.4-orig/drivers/block/tffs/flstruct.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/flstruct.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,847 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ + +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/common/flstruct.h-arc $ + * + * Rev 1.13 Oct 30 2007 17:08:54 einat.avidan + * new fast area type - FL_LENGTH_ALL + * + * Rev 1.12 Oct 22 2007 11:34:54 einat.avidan + * update copyrights header + * + * Rev 1.11 Oct 11 2007 18:50:24 Einat.Avidan + * add compilation flags for SOTP and SLPP + * + * Rev 1.10 Mar 13 2007 13:47:18 einat.avidan + * add support for SLPP + * + * Rev 1.9 Feb 28 2007 09:53:48 einat.avidan + * No change + * + * Rev 1.7.1.3 Sep 11 2006 13:45:24 yaniv.iarovici + * Legal header added + * + * Rev 1.7.1.2 Sep 03 2006 14:45:12 Yaniv.Iarovici + * 1. Added '#define FL_EXT_INFO_NO_SPEC_PART 0xFF'. + * (Indicates SDK not to retrieve specific partition info in certain APIs) + * 2. Encapsulate '#define TL_LEAVE_BINARY_AREA' and '#define TL_LEAVE_SOME_BINARY_AREA' + * under '#ifdef BDK_ACCESS'. + * 3. Define 'TL_LEAVE_SOME_PARTITIONS' with value of 0x9. + * + * Rev 1.7.1.1 Aug 16 2006 08:47:42 Yaniv.Iarovici + * 1) Add '#define TL_LEAVE_SOME_PARTITIONS TL_LEAVE_SOME_BINARY_AREA' + * 2) Encapsulate BDK related defines under '#ifdef BDK_ACCESS'. + * + * Rev 1.7.1.0 Aug 08 2006 15:55:30 Polina.Marimont + * DOC Driver 1.0 initial + */ + +#ifndef FLSTRUCT_H +#define FLSTRUCT_H + +#include "flcommon.h" + + +/**************************************************************************/ +/* Function opcode definitions: */ +/* All TrueFFS functions has a uniques opcodes. The following enum */ +/* defines all the function calls used by the TrueFFS SDK API. */ +/* Note: */ +/* The order of the enum bellow should be strictly kept since the bdcall */ +/* function utilizes the index values to simplify the function search */ +/**************************************************************************/ +typedef enum { +/* The following routines are files related routines */ + + /*********/ + /* FILES */ + /*********/ + + FL_READ_FILE = 0, + FL_WRITE_FILE, + FL_SPLIT_FILE, + FL_JOIN_FILE, + FL_SEEK_FILE, + FL_FIND_NEXT_FILE, + FL_FIND_FILE, + FL_TRUNCATE_FILE, + INDEX_WRITE_FILE_START = 100, + FL_CLOSE_FILE, + FL_FLUSH_FILE, + INDEX_OPENFILES_END = 200, + FL_OPEN_FILE, + FL_DELETE_FILE, + FL_FIND_FIRST_FILE, + FL_GET_DISK_INFO, + FL_RENAME_FILE, + FL_MAKE_DIR, + FL_REMOVE_DIR, + FL_FLUSH_BUFFER, + FL_CLOSE_ALL_FILES, + FL_FLUSH_ALL_FILES, + FL_OPEN_DIRECTORY, + FL_OPEN_MM_FILE, + FL_LAST_FAT_FUNCTION = 300, + + /* The following routines will not perform valid partition check */ + /**********/ + /* BINARY */ + /**********/ + INDEX_BINARY_START = 400, + FL_BINARY_WRITE_INIT, + FL_BINARY_WRITE_BLOCK, + FL_BINARY_CREATE, + FL_BINARY_ERASE, + FL_BINARY_PROTECTION_CHANGE_KEY, + FL_BINARY_PROTECTION_CHANGE_LOCK, + FL_BINARY_PROTECTION_SET_TYPE, + INDEX_BINARY_WRITE_END = 500, + FL_BINARY_READ_INIT, + FL_BINARY_READ_BLOCK, + FL_BINARY_PARTITION_INFO, + FL_BINARY_PROTECTION_GET_TYPE, + FL_BINARY_PROTECTION_INSERT_KEY, + FL_BINARY_PROTECTION_REMOVE_KEY, + INDEX_BINARY_END = 600, + +/* The following routines must be called with partition number 0 */ + INDEX_NEED_PARTITION_0_START = 700, + /* OTP */ + FL_OTP_SIZE, + FL_OTP_READ, + FL_OTP_WRITE, + FL_WRITE_IPL, + FL_READ_IPL, + /* PHYSICAL */ + FL_DEEP_POWER_DOWN_MODE, + FL_GET_PHYSICAL_INFO, + FL_PHYSICAL_READ, + FL_PHYSICAL_WRITE, + FL_PHYSICAL_ERASE, + FL_UPDATE_SOCKET_PARAMS, + FL_UNIQUE_ID, + FL_CUSTOMER_ID, + BD_FORMAT_VOLUME, + BD_FORMAT_PHYSICAL_DRIVE, + FL_PLACE_EXB, + FL_READ_BBT, + FL_WRITE_BBT, + FL_GET_EXTENDED_DISK_INFO, + FL_PROTECTION_STICKY_LOCK, + BD_FLASH_FORMAT, + BD_UNFORMAT, + FL_HW_CONFIG, + FL_RECOVER_FROM_POWER_LOSS, + FL_IPL_PROTECTION_GET_TYPE, + FL_IPL_PROTECTION_REMOVE_KEY, + FL_IPL_PROTECTION_INSERT_KEY, + FL_IPL_PROTECTION_CHANGE_KEY, + FL_IPL_PROTECTION_CHANGE_TYPE, + + INDEX_NEED_PARTITION_0_END = 800, +/* The following routines will go through the volume validity check */ + /* PROTECTION */ + FL_PROTECTION_GET_TYPE, + FL_PROTECTION_REMOVE_KEY, + FL_PROTECTION_INSERT_KEY, + FL_PROTECTION_SET_LOCK, + FL_PROTECTION_CHANGE_KEY, + FL_PROTECTION_CHANGE_TYPE, + FL_COUNT_VOLUMES, + FL_INQUIRE_CAPABILITIES, + /* BDTL */ + FL_MOUNT_VOLUME, + FL_ABS_MOUNT, + BD_FORMAT_LOGICAL_DRIVE, + FL_WRITE_PROTECTION, + FL_DISMOUNT_VOLUME, + FL_CHECK_VOLUME, + FL_DEFRAGMENT_VOLUME, + FL_ABS_WRITE, + FL_ABS_DELETE, + FL_ABS_READ, + FL_ABS_ADDRESS, + FL_GET_BPB, + FL_SECTORS_IN_VOLUME, + FL_VOLUME_INFO, + FL_VERIFY_VOLUME, + FL_CLEAR_QUICK_MOUNT_INFO, + FL_RUGGEDIZE_OPERATION, /* not used */ + FL_ABS_WRITE_UNCOMMITED, /* not used */ + FL_ABS_DELETE_UNCOMMITED, /* not used */ + FL_ABS_READ_RUGGEDIZED, /* not used */ + FL_GET_QUICK_MOUNT_STATUS, + FL_WRITE_QUICK_MOUNT_INFO, + FL_LOAD_VOLUMES_CACHE, + FL_COMPLETE_OPERATION, + FL_FIND_LOGICAL_PARTITION, + FL_CREATE_LOGICAL_PARTITIONS, + FL_FORMAT_FS, + FL_GET_BD_VERSION, + FL_GET_FS_VERSION, + BD_ERASE_BD, + FL_ABS_SECURE_DELETE, + FL_MCOTP_SIZE,/* not used - must gone */ + FL_MCOTP_READ,/* not used - must gone */ + FL_MCOTP_WRITE,/* not used - must gone */ +#ifdef FL_SLPP + FL_SLPP_UNLOCK_RANGE, + FL_SLPP_LOCK_RANGE, + FL_SLPP_UNLOCK_ENTIRE_PARTITION, + FL_SLPP_STICKY_LOCK_RANGE, + FL_SLPP_REPORT_LOCKED_RANGES, +#endif /*FL_SLPP*/ + FL_DOCH_PASS_THROUGH /* DOCH only */ +} FLFunctionNo; + + + +/**************************************************************************/ +/* Structures and defines for GetInfo routines: */ +/* GetInfo routines are used by several TrueFFS packages. */ +/* The output structures and values are defined below */ +/**************************************************************************/ + +/*---------------------------------------------------------*/ +/* V o l u m e I n f o R e c o r d */ +/* */ +/* A structure that holds general information about the */ +/* media. The information includes Physical Info (see */ +/* flGetPhysicalInfo), Logical partition (number of sectors*/ +/* and CHS), boot area size, S/W versions Media life-time */ +/* etc. */ +/* A pointer to this structure is passed to the function */ +/* flVolumeInfo where it receives the relevant data. */ +/*---------------------------------------------------------*/ + +typedef struct { + FLDword logicalSectors; /* number of logical sectors */ + FLDword bootAreaSize; /* boot area size */ + FLDword baseAddress; /* physical base address */ + FLWord flashType; /* JEDEC id of the flash */ + FLDword dwPhysicalSize; /* physical size of the media */ + FLDword dwPhysicalUnitSize;/* Erasable block size */ + FLByte DOCType; /* DiskOnChip type (MDoc/Doc2000) */ + FLSByte lifeTime; /* Life time indicator for the media (1-10) */ + /* 1 - the media is fresh, */ + /* 10 - the media is close to its end of life */ + FLSByte driverVer[10]; /* driver version (NULL terminated string) */ + FLSByte OSAKVer[10]; /* TrueFFS version that driver is based on */ + /* (NULL terminated string) */ + FLDword cylinders; /* Media..... */ + FLDword heads; /* geometry...... */ + FLDword sectors; /* parameters. */ +} VolumeInfoRecord; + + +/*---------------------------------------------------------*/ +/* P h y s i c a l I n f o */ +/* */ +/* A structure that holds physical information about the */ +/* media. The information includes JEDEC ID, unit size and */ +/* media size. Pointer to this structure is passed to the */ +/* function flGetPhysicalInfo where it receives the */ +/* relevant data. */ +/*---------------------------------------------------------*/ + +typedef struct { + FLWord type; /* Flash device type (JEDEC id) */ + FLByte mediaType; /* type of media see below */ + FLDword dwUnitSize; /* Smallest physically erasable size in sectors */ + FLDword dwMediaSize; /* media size in sectors */ + FLDword dwChipSize; /* individual chip size in sectors */ + FLDword interleaving; /* device interleaving */ +} PhysicalInfo; + + + +/*---------------------------------------------------------*/ +/* f l E x t e n d e d D i s k I n f o */ +/* */ +/* This structure supplies very low-level information on */ +/* the device */ +/* */ +/* Note: This structure is used for M-Systems low level */ +/* utilities. It is subject to chages from one TrueFFS*/ +/* version to the other. */ +/* */ +/*---------------------------------------------------------*/ + +typedef struct { + + /******************************************/ + /* Fields that belong to the entire media */ + /******************************************/ + FLDword dwStructSize; /* INPUT - Size of the given structure */ + FLDword dwTLType; /* See definitions in flflash.h */ + FLDword dwFormatFlags; /* Format attributes for the entire media */ + FLDword dwTrueFFSVersion; /* Version of OSAK used to format the media */ + FLDword dwFlashTechnology; /* Flash technology supported properties */ + + FLDword dwType; /* Flash type */ + FLDword dwSubType; /* Sub Flash type */ + FLByte bMediaType; /* Controller family */ + FLByte bNoOfFloors; /* Number of floors in the device */ + FLByte bNoOfPlanes; /* Number of flash planes */ + FLByte bNoOfBanks; /* Number of flash banks */ + FLByte bDataBusWidth; /* Value of the IF_CFG (either 8 or 16 bits)*/ + FLByte bSectorsPerPage; /* Number of sectors in a flash page */ + FLByte bSharedSectors; /* The minimal number of logical sectors */ + /* that might be affected by one another */ + /* write operation. */ + FLByte bFastAreaSharedSectors; /* Minimal number of sectors that can affect */ + /* one another when written in fast mode. */ + FLByte bMaxRelatedSectors; /* Max number of sectors that might share */ + /* the same write operation or might be */ + /* affected by each other write operation. */ + FLDword dwIPLSize; /* Number of bytes of SRAM in the device */ + FLByte bChangeableProtectedAreas; /* Number of protection areas capable */ + /* of changing. */ + FLByte btotalProtectedAreas; /* Total number of protection areas */ + FLDword dwUnitsInFirstFloor; /* Number of units in the first floor */ + FLDword dwUnitSize; /* Size of logical erasable unit */ + FLDword dwMaxBadPercentage; /* Flash guaranteed worst bad blocks percentage */ + FLByte bNoOfBinaryPartitions; /* Number of binary partition on the media */ + FLByte bNoOfDiskPartitions; /* Number of disk partition on the media */ + FLByte bBlockMultiplierBits; /* no of bits used to represent the time a */ + /* flash logical unit fits inside in a TL */ + /* erasable unit. */ + FLByte dwPercentUsed; /* Percent of the media to be exported */ + FLByte bHeaderUnits; /* Number of units reserved in the begining */ + /* of each floor for the media header */ + FLWord wHeaderLocation; /* Unit number where the header of the */ + /* current floor resides. In case all floors*/ + /* are requested, the value should indicate */ + /* the location of the header in the first */ + /* floor. */ + + FLByte bProgrammerNamePtr[4]; /* Programmer name */ + FLByte bProgrammerVersionPtr[4]; /* Programmer version */ + + /************************************************/ + /* Fields that belong to the specific partition */ + /************************************************/ + + FLDword dwVirtualUnits; /* Virtual size exported by the translation layer */ + /* Note some units are smaller then others */ + FLDword dwFastUnits; /* Number of virtual units that are fast units */ + FLDword dwFirstQuickMountUnit; /* First unit used for the quick mount data */ + FLDword dwFirstUnit; /* First unit of the partition */ + FLDword dwLastUnit; /* Last unit of the partition */ + FLDword dwSpareUnits; /* Number of spare units requested by the user */ + FLDword dwTransferUnits; /* Number of transfer units used for chaining */ + FLDword dwPartitionFlags;/* See list above "Partition flags" */ + FLDword dwNormalAreaUnitSize; /* Logical size of a TL normal unit */ + FLDword dwFastAreaLogicalUnitSize; /* Logical size of a TL fast unit */ + FLDword dwFastAreaVirtualFactor; /* Virtual unit factor between fast */ + /* and normal area (power of 2) */ + + FLByte bMinSectorsForFolding; /* Number of sectors to be copied */ + /* together in a folding operation */ + FLByte bMinSectorsForNextWrite; /* For performance reasons the TL */ + /* decide to reduce the above value */ + FLByte bfastAreaMinSectorsForNextWrite; /* For performance reasons the TL */ + /* decide to reduce the above value */ + + /******************************************/ + /* Fields that are valid only after mount */ + /******************************************/ + + FLDword dwUsedUnits; /* Number of used virtual chains */ + FLDword dwFreeUnits; /* Number of currently free units */ + FLByte bNeededFreeUnits; /* Minimal number of free units */ + /* before folding */ + FLDword dwUMDBBTSector; /* Location of latest UMDBBT sector */ +} FLExtendedDiskInfo; + +/* media types */ +#define FL_NOT_DOC 0 +#define FL_DOC 1 +#define FL_MDOC 2 +#define FL_DOC2000TSOP 3 +#define FL_MDOCP_16 4 +#define FL_MDOCP 5 +#define FL_DOC_H1 6 +#define FL_MDOC512_G3 7 +#define FL_MDOC256_P3 8 +#define FL_MDOC256_G3 9 +#define FL_MDOC128_P3 10 +#define FL_AMD_NOR 11 +#define FL_SEIJA 12 +#define FL_MDOC_G4 13 +#define FL_MDOC_P4 14 +#define FL_H3 15 + +/*Defines for flExtendedDiskInfo*/ +#define SAFTL_ADVANCED_MATCHING 0x00100000L +#define SAFTL_QUICK_MOUNT 0x10000000L + +#define FL_BDK_PARTITION 1 +#define FL_DISK_PARTITION 0 +#define FL_ALL_FLOORS 0xff +#define BINARY_SPARE_BLOCKS_SIGN "S4BB" /* Must be the same as BINARY_SPARE_BLOCKS_SIGN (FLFORMAT.H) */ + +#define FL_EXT_INFO_NO_SPEC_PART 0xFF /*Indicates SDK not to retrieve specific partition info*/ + + +/**************************************************************************/ +/* Structures and defines for Format routines: */ +/**************************************************************************/ + +typedef FLStatus (*FLProgressCallback)(FLWord totalUnitsToFormat, FLWord totalUnitsFormattedSoFar); + +/*----------------------------------------------*/ +/* User BDTL Partition Format Parameters record */ +/*----------------------------------------------*/ + +typedef struct { +FLDword length; + /* The size in bytes of the usable storage space. The size + rounded upwards to a multiplication of a block size. + The size of the last partition will calculated automatically, + but if the requested size is greater then the remaining space + an error code will be returned,. Requesting zero size for any + partition but the last will generate an flBadParameters status. */ +FLDword fastAreaLength; +FLWord lengthType; +FLWord fastAreaLengthType; +FLWord fastAreaVirtualFactor; /* Should be set to FL_NORMAL_SPACING */ +FLWord noOfSpareUnits; + /* BDTL needs at least one spare erase unit in order to function + as a read/write media. It is possible to specify more than one + spare unit, which takes more media space. The advantage of + specifying more than one spare unit is that if one of the flash + erase units becomes bad and un-erasable in the future, then one + of the spare units can replace it. In that case, a second spare + unit enables TrueFFS to continue its read/write functionality, + whereas if no second spare unit is available the media goes into + read-only mode. The standard value used is 3 */ + +FLDword BDTLFP_0_RFU_0; /* Reserved 0 */ +FLDword BDTLFP_1_RFU_0; /* Reserved 0 */ +FLDword BDTLFP_2_RFU_0; /* Reserved 0 */ +FLDword BDTLFP_3_RFU_0; /* Reserved 0 */ + +FLByte protectionKey[8]; /* The key for the protection*/ +FLByte protectionType; + /* PROTECTABLE - Can receive protection */ + /* READ_PROTECTED - Protect against read operations */ + /* WRITE_PROTECTED - Protect against write operations */ + /* LOCK_ENABLED - Enables the hardware lock signal */ + /* PROTECTABLE - This partition can be protected */ + /* CHANGEABLE_PROTECTION - protection type can be changed */ + /* The ratio between the real media size and the virtual size + reported to the file system when compression is active. */ +} BDTLPartitionFormatParams3; + +/*------------------------------------------------*/ +/* User binary Partition Format Parameters record */ +/*------------------------------------------------*/ + +typedef struct { +FLDword length; /* Required number of usable bytes (rounded to units) */ + /* in the partition. */ + +FLWord lengthType; /* Must be FL_LENGTH_IN_BYTES */ + +FLByte sign[4]; /* signature of the binary partition to format. + The signature 0xFFFF FFFF is not a valid signature */ + +FLDword flags; /* TL_NORMAL_FORMAT / TL_SPL_FORMAT */ + +FLWord spareBlocks; /* Spare blocks for DBB support */ + +FLDword BDKFP_0_RFU_0; /* Reserved 0 */ +FLDword BDKFP_1_RFU_0; /* Reserved 0 */ +FLDword BDKFP_2_RFU_0; /* Reserved 0 */ +FLDword BDKFP_3_RFU_0; /* Reserved 0 */ + +/* TL_NORMAL_FORMAT / TL_SPL_FORMAT */ + +FLByte protectionKey[8]; /* The key for the protection*/ +FLByte protectionType; + /* PROTECTABLE - Can receive protection */ + /* READ_PROTECTED - Protect against read operations */ + /* WRITE_PROTECTED - Protect against write operations */ + /* LOCK_ENABLED - Enables the hardware lock signal */ + /* PROTECTABLE - This partition can be protected */ + /* CHANGEABLE_PROTECTION - protection type can be changed */ +} BinaryPartitionFormatParams3; + + +/*---------------------------------------------------------*/ +/* User Format Parameters record for flFlashFormat routine */ +/*---------------------------------------------------------*/ + + +typedef struct { + +/*****************************/ +/* Device formatting section */ +/*****************************/ + +FLByte percentUse; + /* NAND flash inherently contains some bad blocks. TrueFFS handles + * those blocks by managing a pool of spare blocks also called transfer + * units. This format parameter specifies the percentage of the media + * to use. + * + * Starting from TrueFFS 6.3.0 alpha 4 this field is no longer a + * configurable formatting argument. You must set this field to + * TL_DEFAULT_PERCENTAGE, letting TrueFFS to choose this value for you. + */ + +FLByte noOfBDTLPartitions; + /* Indicates the number of Disk partition (1 to 4). */ + +FLByte noOfBinaryPartitions; + /* Indicates the number of binary partitions (up to 3). 0 will + * cause formatting with no binary partition. This value is ignored + * if TL_LEAVE_BINARY_AREA flag is set in the irFlags field the ioreq + */ + +BDTLPartitionFormatParams3 FAR2* BDTLPartitionInfo; + /* BDTL partition information array */ + +BinaryPartitionFormatParams3 FAR2* binaryPartitionInfo; + /* Binary partition information array*/ + +/***********************************/ +/* Special format features section */ +/***********************************/ + +FLByte cascadedDeviceNo; /* Not used */ + +FLByte noOfCascadedDevices; /* Not used */ + +FLProgressCallback progressCallback; + /* Progress callback routine, will be called if not NULL. + The callback routine is called after erasing each unit, + and its parameters are the total number of erase units + to format and the number erased so far. + The callback routine returns a Status value. A value of + OK (0) allows formatting to continue. Any other value + will abort the formatting with the returned status code. */ + /* In case the FL_REPORT_MOUNT_PROGRESS compilation flag is set the + routine will also report the mount progress of the mount routine + for each of the Disk partitions. A 0,0 return values will report + the end of a format status and of a mount operation */ + +FLDword FP_0_RFU_0; /* Reserved 0 */ + +FLDword FP_1_RFU_0; /* Reserved 0 */ + +/* Note the following section is not used by for DiskOnChips */ +/*************************************************************/ + +FLSDword bootImageLen; /* Reserved 0 */ + +FLDword vmAddressingLimit; /* Reserved 0 */ + +FLWord embeddedCISlength; /* Reserved 0 */ + +FLByte FAR1 * embeddedCIS; /* Reserved NULL */ +} FormatParams3; + +/*--------------------------------------------------*/ +/* Flags for format routine (non partition related) */ +/*--------------------------------------------------*/ +#ifdef BDK_ACCESS +#define TL_LEAVE_BINARY_AREA 0x8 /* Is assumed to be a single bit */ +#define TL_LEAVE_SOME_BINARY_AREA 0x9 /* Must include TL_LEAVE_BINARY_AREA bits */ +#endif /*BDK_ACCESS*/ + +#define TL_SINGLE_FLOOR 0x10 /* Format only a selection of the floors */ +#define TL_DO_NOT_PERFORM_DOWNLOAD 0x20 /* Do not issue a download operation at */ + /* end of the format routine. */ +#define TL_FAIL_ON_UNMARKED_BB 0x80 /* Fail in case an unmarked bad block is */ + /* Found. */ + +#define TL_LEAVE_SOME_PARTITIONS 0x9 + +/*--------------------------------------------------*/ +/* Formatting parameter structure definition */ +/*--------------------------------------------------*/ +#define FL_LENGTH_IN_BYTES 0 +#define FL_LENGTH_IN_SECTORS 1 +#define FL_LENGTH_IN_UNITS 2 +#define FL_LENGTH_IN_PERCENTS 3 +#define FL_LENGTH_IN_CYLINDERS 10 +#define FL_LENGTH_ALL 20 + +/*--------------------------------------------------*/ +/* Internal Partition flags - N O T F O R U S E */ +/*--------------------------------------------------*/ +#define TL_SIMPLE_MATCHING 0x10 /* Use simple matching for partition */ +#define TL_FORCE_REL 0x20 /* Use RELIABLE mode */ +#define TL_FAST_MODE 0x40 /* Use FAST mode */ +#define TL_NO_PLANES 0x80 /* Do not match blocks for planes */ + +/*--------------------------------------------------*/ +/* External Disk Partition Flags (TL_NORMAL_FORMAT):*/ +/*--------------------------------------------------*/ +#define TL_NORMAL_FORMAT 0 + +#ifdef BDK_ACCESS +/*--------------------------------------------------*/ +/* External Binary Partition Flags */ +/* (TL_NORMAL_FORMAT / TL_SPL_FORMAT) */ +/*--------------------------------------------------*/ +#define TL_SPL_FORMAT (TL_SIMPLE_MATCHING | TL_NO_PLANES | TL_FORCE_REL) /* SPL partition */ +#endif /*BDK_ACCESS*/ + +/*--------------------------------------------------*/ +/* External spacing factors - only 1 value */ +/*--------------------------------------------------*/ +#define FL_NORMAL_SPACING 1 + +/*--------------------------------------------------*/ +/* Standard initializer for */ +/* BDTLPartitionFormatParams3 structure */ +/*--------------------------------------------------*/ + +#define TL_DEFAULT_PERCENTAGE 0 /* Use default percentage of the media */ +#define TL_NO_BOOST 0 /* Do not use any performance boost */ +#define TL_BASIC_BOOST 1 /* Use basic 1% performance boost */ +#define TL_ENHANCED_PERFORMANCE 100 /* Define as enhanced performance partition */ + +#define TL_BDTL_STD_SPACE_FACTOR FL_NORMAL_SPACING +#define TL_BDTL_STD_SPARE_UNITS_NO 3 +#define STD_BDTL_PARAMS3 {0, /* Total Length */ \ + 0, /* Fast Length */ \ + FL_LENGTH_IN_BYTES, /* Total Length type */ \ + FL_LENGTH_IN_SECTORS, /* Fast Length type */ \ + TL_BDTL_STD_SPACE_FACTOR,/* Spaced Factor */ \ + TL_BDTL_STD_SPARE_UNITS_NO,/* No of spare units */ \ + 0,0,0,0, /* Reserved 0 */ \ + {0,0,0,0,0,0,0,0},0} /* No H/W protection */ + +/*--------------------------------------------------*/ +/* Standard initializer for */ +/* BinaryPartitionFormatParams3 structure */ +/*--------------------------------------------------*/ +#define TL_BDK_STD_SPARE_BLOCKS_NO 1 +#define STD_BINARY_PARAMS3 {0, /* Partition length */ \ + FL_LENGTH_IN_BYTES, /* Partition length type */ \ + {'B','I','P','O'}, /* Signature */ \ + 0, /* 0 -normal partition , TL_SPL_FORMAT for SPL Partition */ \ + TL_BDK_STD_SPARE_BLOCKS_NO,/* Number of spare blocks */ \ + 0,0,0,0, /* Reserved 0 */ \ + {0,0,0,0,0,0,0,0}, /* Protection key */ \ + 0} /* Protection type */ \ + +/*--------------------------------------------------*/ +/* Standard initializer for FormatParams3 structure */ +/*--------------------------------------------------*/ +#define STD_FORMAT_PARAMS3 {TL_DEFAULT_PERCENTAGE, /* Percent used */ \ + 1, /* No of Disk Partitions */ \ + 0, /* No of Binary Partitions */ \ + NULL, /* Disk partition structure */ \ + NULL, /* Binary partition structure */ \ + 0, /* This cascaded device */ \ + 0, /* Total cascaded devices */ \ + NULL, /* Progress call back */ \ + 0, 0, /* Reserved 0 */ \ + 0, 0, 0, NULL} /* Reserved 0 */ + + + +#ifdef BDK_ACCESS +/**************************************************************************/ +/* Structures and defines for BDK routines: */ +/**************************************************************************/ +#define BDK_SIGNATURE_NAME 4 + +typedef struct { + FLByte oldSign[BDK_SIGNATURE_NAME]; + FLByte newSign[BDK_SIGNATURE_NAME]; + FLByte signOffset; + FLDword startingBlock; + FLDword length; + FLByte flags; + FLByte FAR1 *bdkBuffer; +} BDKStruct; + +#define ERASE_BEFORE_WRITE 8 + +#endif /*BDK_ACCESS*/ + + +/**************************************************************************/ +/* Defines for Defrag routines: */ +/**************************************************************************/ +#define FL_MINIMAL_DEFRAGMENTATION -1 +#define FL_MAXIMUM_DEFRAGMENTATION -20 +#define FL_STATIC_WEAR_LEVELING_DELAYED -2 +#define FL_STATIC_WEAR_LEVELING_NOW -3 +#define FL_STATIC_WEAR_LEVELING_ON -4 +#define FL_STATIC_WEAR_LEVELING_OFF -5 + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED +typedef struct { + FLByte jumpInstruction[3]; + FLSByte OEMname[8]; + Unaligned bytesPerSector; + FLByte sectorsPerCluster; + LEushort reservedSectors; + FLByte noOfFATS; + Unaligned rootDirectoryEntries; + Unaligned totalSectorsInVolumeDOS3; + FLByte mediaDescriptor; + LEushort sectorsPerFAT; + LEushort sectorsPerTrack; + LEushort noOfHeads; + LEulong noOfHiddenSectors; + LEulong totalSectorsInVolume; +} BPB; +#else /*FL_NO_PACKED_STRUCTS_SUPPORTED*/ +#define FL_BPB_JUMP_INSTRUCTION_OFFSET 0 /* size 3, array */ +#define FL_BPB_OEM_NAME_OFFSET 3 /* size 8, array */ +#define FL_BPB_BYTES_PER_SECTOR_OFFSET 11 /* size 2, unaligned */ +#define FL_BPB_SECTORS_PER_CLUSTER_OFFSET 13 /* size 1 */ +#define FL_BPB_RESERVED_SECTORS_OFFSET 14 /* size 2 */ +#define FL_BPB_NO_OF_FATS_OFFSET 16 /* size 1 */ +#define FL_BPB_ROOT_DIR_ENTRIES_OFFSET 17 /* size 2, unaligned */ +#define FL_BPB_TOTAL_SECTORS_IN_VOL_DOS3_OFFSET 19 /* size 2, unaligned */ +#define FL_BPB_MEDIA_DESCRIPTOR_OFFSET 21 /* size 1 */ +#define FL_BPB_SECTORS_PER_FAT_OFFSET 22 /* size 2 */ +#define FL_BPB_SECTORS_PER_TRACK_OFFSET 24 /* size 2 */ +#define FL_BPB_NO_OF_HEADS_OFFSET 26 /* size 2 */ +#define FL_BPB_NO_OF_HIDDEN_SECTORS_OFFSET 28 /* size 4 */ +#define FL_BPB_TOTAL_SECTORS_IN_VOL_OFFSET 32 /* size 4 */ +#define FL_BPB_SIZE 36 +typedef FLByte BPB[FL_BPB_SIZE]; +#endif /*FL_NO_PACKED_STRUCTS_SUPPORTED*/ +typedef struct { +FLDword length; +FLWord lengthType; +FLByte pType; +FLByte flags; +}LogicalPartitionParams; + +#define STD_LOG_PARTITION_PARAMS {0, /* Partition length */ \ + FL_LENGTH_IN_BYTES, /* Bytes, Sectors ... */ \ + DOS4_PARTIT, /* Partition type */ \ + FL_MARK_PARTITION_BOOTABLE}/* Either bootable or not */ \ + +typedef struct { +SectorNo bootSectorNo; +SectorNo sectorsInVolume; +SectorNo MBR; +int MBRslot; +} LogPartitionInfo; + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED +typedef struct { + FLSByte name[11]; + FLByte attributes; /* mapped below */ + FLByte lowerCaseFlags; + FLByte createTimeMilisec; + LEushort createTimeHourMin; + LEushort createDate; + LEushort lastAccessedDate; + LEushort reserved1; + LEushort updateTime; + /* The date field is encoded as follows: */ + /* bit 0-4: Day of month (1-31) */ + /* bit 5-8: Month (1-12) */ + /* bit 9-15: Year relative to 1980 */ + LEushort updateDate; + /* The DOS time field is encoded as follows: */ + /* bit 0-4: seconds divided by 2 (0-29) */ + /* bit 5-10: minutes (0-59) */ + /* bit 11-15: hours (0-23) */ + LEushort startingCluster; + LEulong fileSize; +} DirectoryEntry; +#else /*FL_NO_PACKED_STRUCTS_SUPPORTED*/ +#define FL_DIRECTORY_ENTRY_NAME_OFFSET 0 /* size 11, array */ +#define FL_DIRECTORY_ENTRY_ATTRIBUTES_OFFSET 11 /* size 1 */ +#define FL_DIRECTORY_ENTRY_LOWERCASE_FLAGS_OFFSET 12 /* size 1 */ +#define FL_DIRECTORY_ENTRY_CREATE_TIME_MILLISEC_OFFSET 13 /* size 1 */ +#define FL_DIRECTORY_ENTRY_CREATE_TIME_HOURMIN_OFFSET 14 /* size 2 */ +#define FL_DIRECTORY_ENTRY_CREATE_DATE_OFFSET 16 /* size 2 */ +#define FL_DIRECTORY_ENTRY_LAST_ACCESS_DATE_OFFSET 18 /* size 2 */ +#define FL_DIRECTORY_ENTRY_RESERVED1_OFFSET 20 /* size 2 */ +#define FL_DIRECTORY_ENTRY_UPDATE_TIME_OFFSET 22 /* size 2 */ +#define FL_DIRECTORY_ENTRY_UPDATE_DATE_OFFSET 24 /* size 2 */ +#define FL_DIRECTORY_ENTRY_STARTING_CLUSTER_OFFSET 26 /* size 2 */ +#define FL_DIRECTORY_ENTRY_FILESIZE_OFFSET 28 /* size 4 */ +#define FL_DIRECTORY_ENTRY_SIZE 32 +typedef FLByte DirectoryEntry[FL_DIRECTORY_ENTRY_SIZE]; +#endif /*FL_NO_PACKED_STRUCTS_SUPPORTED*/ +/* FAT Format Parameters record - given to flFormatFS */ + +typedef struct { +FLWord noOfRootEntries; +FLWord noOfSectorsPerCluster; +FLByte noOfFATs; +FLByte pType; +FLByte reserved1; +FLByte flags; +FLByte volumeId[4]; /* FAT partition identification number */ +FLByte* volumeLabel; /* FAT partition label string. If NULL, no label */ +} FATFormatParams; + + +#define FAT12_PARTIT 0x01 +#define FAT16_PARTIT 0x04 +#define EX_PARTIT 0x05 +#define DOS4_PARTIT 0x06 +#define FAT32_PARTIT 0x0b + +#define FL_TFAT_MODE 0x1 + +#define FS_USE_DEFAULT_CLUSTER_SIZE 0 + +#define STD_FAT_FORMAT_PARAMS {512, /* No of entries in the rood directory */ \ + FS_USE_DEFAULT_CLUSTER_SIZE, /* No of sectors per cluster */ \ + 1, /* No of FAT copies */ \ + 0, /* Partition type */ \ + 0, 0, /* Reseved 0 */ \ + {0, 0, 0, 0}, /* FAT Volume ID */ \ + NULL} /* FAT Lable */ + + +#endif /* FLSTRUCT_H */ diff -urN linux-2.6.30.4-orig/drivers/block/tffs/flsysfun.h linux-2.6.30.4/drivers/block/tffs/flsysfun.h --- linux-2.6.30.4-orig/drivers/block/tffs/flsysfun.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/flsysfun.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,239 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/3/common/flsysfun.h-arc $ + * + * Rev 1.8 Oct 22 2007 11:34:54 einat.avidan + * update copyrights header + * + * Rev 1.7 Sep 11 2006 13:45:24 yaniv.iarovici + * Legal header added + * + * Rev 1.6 Aug 09 2006 16:52:52 Polina.Marimont + * initial for DOC Driver 1.0 + */ + +#ifndef FLSYSFUN_H +#define FLSYSFUN_H + + +/*----------------------------------------------------------------------*/ +/* f l S y s f u n I n i t */ +/* */ +/* Do any necessary initialization for routines in this module. */ +/* */ +/* Called from fatlite.c (flInit) */ +/* */ +/* Parameters: */ +/* None */ +/* */ +/*----------------------------------------------------------------------*/ + +extern void flSysfunInit(void); + + +/*----------------------------------------------------------------------*/ +/* f l R a n d B y t e */ +/* */ +/* Returns a random number between 0 and 255 */ +/* */ +/* Called from FTLLITE.C */ +/* */ +/* Parameters: */ +/* None */ +/* */ +/* Returns: */ +/* A random number between 0 and 255 */ +/*----------------------------------------------------------------------*/ + +extern unsigned flRandByte(void); + + +/*----------------------------------------------------------------------*/ +/* f l I n s t a l l T i m e r */ +/* */ +/* Installs an interval timer. */ +/* The implementation of this routine usually means hooking a clock */ +/* interrupt. The polling interval is specified as a parameter. If the */ +/* clock frequency is faster, the interval timer should count several */ +/* clock ticks before calling the interval routine. */ +/* */ +/* This routine is necessary if POLLING_INTERVAL (custom.h) is greater */ +/* than 0. In this case this routine will be called from socket.c */ +/* (init). It will be called to install 'socketIntervalRoutine' with a */ +/* period specified by POLLING_INTERVAL. */ +/* */ +/* Parameters: */ +/* routine : Routine to call at each interval */ +/* interval : Milliseconds per polling interval */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failure */ +/*----------------------------------------------------------------------*/ + +extern FLStatus flInstallTimer(void (*routine)(void), unsigned interval); + + +#ifdef FL_EXIT + +/*----------------------------------------------------------------------*/ +/* f l R e m o v e T i m e r */ +/* */ +/* Removes the active interval timer. */ +/* This routine removes the active interval timer set by 'removeTimer'. */ +/* */ +/* Parameters: */ +/* None */ +/* */ +/*----------------------------------------------------------------------*/ + +extern void flRemoveTimer(void); + +#endif + + +/*----------------------------------------------------------------------*/ +/* f l C u r r e n t D a t e */ +/* */ +/* Returns the current DOS-format date */ +/* */ +/* The DOS date format is documented in dosformt.h. */ +/* */ +/* If a TOD clock is not available, return the value of 1/1/80. */ +/* */ +/* Parameters: */ +/* None */ +/* */ +/* Returns: */ +/* Current date */ +/*----------------------------------------------------------------------*/ + +extern unsigned flCurrentDate(void); + + +/*----------------------------------------------------------------------*/ +/* f l C u r r e n t T i m e */ +/* */ +/* Returns the current DOS-format time */ +/* */ +/* The DOS time format is documented in dosformt.h. */ +/* */ +/* If a TOD clock is not available, return the value of 0:00 AM. */ +/* */ +/* Parameters: */ +/* None */ +/* */ +/* Returns: */ +/* Current time */ +/*----------------------------------------------------------------------*/ + +extern unsigned flCurrentTime(void); + + +/*----------------------------------------------------------------------*/ +/* f l C r e a t e M u t e x */ +/* */ +/* Creates and initializes a mutex object */ +/* */ +/* The mutex is initializes as not owned by anyone. */ +/* */ +/* Parameters: */ +/* mutex : Pointer to mutex object */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failure */ +/*----------------------------------------------------------------------*/ + +extern FLStatus flCreateMutex(FLMutex *mutex); + + +/*----------------------------------------------------------------------*/ +/* f l D e l e t e M u t e x */ +/* */ +/* Destroys a mutex object */ +/* */ +/* This function frees any resources taken by flCreateMutex. */ +/* */ +/* Parameters: */ +/* mutex : Pointer to mutex object */ +/* */ +/* Returns: */ +/* None */ +/*----------------------------------------------------------------------*/ + +extern void flDeleteMutex(FLMutex *mutex); + + +/*----------------------------------------------------------------------*/ +/* f l T a k e M u t e x */ +/* */ +/* Attempts to take ownership of a mutex. If the mutex is currently not */ +/* owned, TRUE is returned and the mutex becomes owned. If the mutex is */ +/* currently owned, FALSE is returned and ownership is not taken. */ +/* */ +/* Parameters: */ +/* mutex : Pointer to mutex object */ +/* */ +/* Returns: */ +/* FLBoolean : TRUE if ownership taken, FALSE otherwise */ +/*----------------------------------------------------------------------*/ + +extern FLBoolean flTakeMutex(FLMutex *mutex); + + +/*----------------------------------------------------------------------*/ +/* f l F r e e M u t e x */ +/* */ +/* Frees ownership of a mutex */ +/* */ +/* Parameters: */ +/* mutex : Pointer to mutex object */ +/* */ +/* Returns: */ +/* None */ +/*----------------------------------------------------------------------*/ + +extern void flFreeMutex(FLMutex *mutex); + + +#endif /* FLSYSFUN_H */ diff -urN linux-2.6.30.4-orig/drivers/block/tffs/flsystem.c linux-2.6.30.4/drivers/block/tffs/flsystem.c --- linux-2.6.30.4-orig/drivers/block/tffs/flsystem.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/flsystem.c 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,720 @@ +/****************************************************************************** + * * + * Project: DOC Driver for Linux 2.6 Block device driver for mDOC H3 family * + * of devices under Linux kernel 2.6. * + * * + * Version: 1.0 * + * Email questions to: oemsupport@sandisk.com * + * Copyright (C) SanDisk IL Ltd. 1995 - 2007 * + * SanDisk IL Ltd., 7 Atir Yeda Street, Kfar Saba 44425, Israel * + * * + ****************************************************************************** + * * + * 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 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, which is set forth in the readme.txt file. * + * 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., 51 * + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + * * + * This License does not grant you any right to use the trademarks, service * + * marks or logos of SanDisk IL Ltd. or SanDisk Corporation. * + * Subject to the foregoing, SanDisk IL Ltd., for itself and on behalf of its * + * licensors, hereby reserves all intellectual property rights in the program,* + * except for the rights expressly granted in this License. * + * * + ******************************************************************************/ + +/* + * $Log$ + */ + + + +/* + * includes + */ + +#include "tffsdrv.h" +#include "flbase.h" +#include "doch_sys.h" +#include "hib.h" + + +#ifdef TFFS_MESSAGES_ENABLED +int fl_debug = FL_DEBUG_DEF; +module_param(fl_debug, int, (S_IRUGO | S_IWUSR)); +MODULE_PARM_DESC(fl_debug,"Print TrueFFS debug messages [0-7]."); +#endif + +/* For portability reasons, Linux drivers should use macros readXXX/writeXXX + * when reading/writing hardware registers and transferring data from + * devices. Command line parameter "tffs_memcpy=<1|2|3>" allows DiskOnChip + * driver to use memcpy() library routine instead, which often greatly + * improves driver's 'read' performance. + * + * insmod tffs.o tffs_memcpy=1 + */ +int tffs_memcpy = 0; +module_param(tffs_memcpy, int, S_IRUGO); +MODULE_PARM_DESC(tffs_memcpy, "Use memcpy() for DiskOnChip data transfers."); + + +/* Command line parameter "tffs_addr=" allows user to tell + * DiskOnChip driver where to look for DiskOnChip. For example, to instruct + * driver to probe for DiskOnChip at physical address 0x14000000: + * + * insmod tffs.o tffs_addr=0x14000000 + */ +ulong tffs_addr[FL_SOCKETS] = { TFFS_PHYS_ADDR }; +static int __fl_sockets = FL_SOCKETS; /* just for module_param_array() below */ +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,9)) + module_param_array(tffs_addr, ulong, __fl_sockets, S_IRUGO); +#else + module_param_array(tffs_addr, ulong, &__fl_sockets, S_IRUGO); +#endif +MODULE_PARM_DESC(tffs_addr,"Physical address of DiskOnChip."); + +/* Command line parameter "tffs_skip_sleeps=" instructs DiskOnChip driver + * how often it should yield CPU during DiskOnChip 'write' operations. The + * higher the , the less frequently driver yield CPU, thus increasing + * it's 'write' performance, but also increasing it's load on CPU. + * + * insmod tffs.o tffs_skip_sleep=3 + */ +int tffs_skip_sleeps = 5; +module_param(tffs_skip_sleeps, int, (S_IRUGO | S_IWUSR)); +MODULE_PARM_DESC(tffs_skip_sleeps,"How often to yield CPU during write operations."); + + +unsigned int profiling[10] = {0}; + + + +/* + * static routines + */ +static void TffsMapMem (SocketInfo *psoc, unsigned long phys_addr, unsigned long length); +static void TffsUnmapMem (SocketInfo *psoc); +static void irq_wait_timed_out (unsigned long arg); + + + +/* + * static vars + */ + +/* semaphore used by TrueFFS: one per socket, plus one for dochVol.mutex */ +static struct semaphore sems [FL_SOCKETS + 1]; + +/* next TrueFFS semaphore to allocate (0..FL_SOCKETS-1) */ +static int total_sems = 0; + + + + +/*-----------------------------------------------------------------------* + * * + * T f f s M a p M e m * + * * + * Allocate physical memory region, and map it into kernel's address * + * space. * + * * + * Parameters: * + * psoc socket pointer * + * phys_addr starting address of physical memory region * + * length length (in bytes) of this physical memory region * + * * + *-----------------------------------------------------------------------*/ +static +void TffsMapMem ( SocketInfo * psoc, + unsigned long phys_addr, + unsigned long length ) +{ + struct resource * rs; + + /* no memory region has been obtained yet */ + psoc->fMemRequested = 0; + psoc->dwPhysAddr = 0; + psoc->dwMappedLen = 0; + psoc->dwVirtAddr = 0; + + /* request physical memory region that DiskOnChip resides in */ + if ((rs = request_mem_region(phys_addr, length, "tffs")) != NULL) + { + /* map this physical memory region to kernel's virtual addr. space */ + if ((psoc->dwVirtAddr = (ulong)ioremap_nocache(phys_addr, length)) != 0) + { + psoc->fMemRequested = 1; + psoc->dwPhysAddr = phys_addr; + psoc->dwMappedLen = length; + } + else + { + PrintkDebug("ioremap_nocache(0x%lx,0x%lx) failed", phys_addr, length); + release_mem_region (phys_addr, length); + } + } + else + { PrintkDebug("request_mem_region(0x%lx,0x%lx) failed", phys_addr, length); } +} + + + + +/*-----------------------------------------------------------------------* + * * + * T f f s U n m a p M e m * + * * + * Unmap and free memory region previously allocated by TffsMapMem(). * + * * + * Parameters: * + * psoc socket pointer * + * * + *-----------------------------------------------------------------------*/ +static +void TffsUnmapMem ( SocketInfo * psoc ) +{ + if (psoc->dwVirtAddr != 0) + iounmap ((void *)psoc->dwVirtAddr); + + if (psoc->fMemRequested == 1) + release_mem_region (psoc->dwPhysAddr, psoc->dwMappedLen); + + psoc->fMemRequested = 0; + psoc->dwPhysAddr = 0; + psoc->dwMappedLen = 0; + psoc->dwVirtAddr = 0; +} + + + + +void * TffsMalloc (unsigned long size) +{ + return vmalloc (size + 4); +} + + + + +void TffsFree (void * vptr) +{ + vfree (vptr); +} + + + + +int LnxTffsPrint(const char *fmt, ...) +{ + va_list args; + char buf[1024]; /* hopefully enough, kernel/printk.c thinks so */ + int i; + + va_start(args, fmt); + i = vsprintf(buf, fmt, args); + va_end(args); + buf[i] = '\0'; + + while(i>0) + { + if(buf[i-1]==0xd || buf[i-1]==0xa) + { + buf[--i]=0; + } + else + break; + } + printk(KERN_ERR TFFS_DEVICE_NAME": %s\n",buf); + return i; +} + + + +/*-----------------------------------------------------------------------* + * * + * t f f s _ r e a d w * + * * + * This routine transfers data from RAM to DiskOnChip device in cases * + * when DMA is not used. * + * * + * Parameters: * + * io_vaddr virtual address of DiskOnChip's data port * + * vbuf buffer to transfer data from * + * words number of 16-bit short words to transfer * + * * + *-----------------------------------------------------------------------*/ + +void tffs_readw ( unsigned long io_vaddr, short * vbuf, int words ) +{ + if (tffs_memcpy & 1) /* use memcpy() to transfer data; might not work ! */ + { + register char * p = (char *) vbuf; + register int n; + + for (words <<= 1; words > 0; words -= n, p += n) + { + /* DiskOnChip's I/O register is aliased across 1024-bytes region */ + n = ((words <= 1024) ? words : 1024); + memcpy (p, (void *)io_vaddr, n); + } + } + else /* standard Linux case: use __raw_readw for portability */ + { + while (words--) + *vbuf++ = __raw_readw (io_vaddr); + } +} + + + +/*-----------------------------------------------------------------------* + * * + * t f f s _ w r i t e w * + * * + * This routine transfers data from DiskOnChip device to RAM in cases * + * when DMA is not used. * + * * + * Parameters: * + * io_vaddr virtual address of DiskOnChip's data port * + * vbuf buffer to transfer data to * + * words number of 16-bit short words to transfer * + * * + *-----------------------------------------------------------------------*/ + +void tffs_writew ( unsigned long io_vaddr, short * vbuf, int words ) +{ + if (tffs_memcpy & 2) /* use memcpy() to transfer data; might not work ! */ + { + register char * p = (char *) vbuf; + register int n; + + for (words <<= 1; words > 0; words -= n, p += n) + { + /* DiskOnChip's I/O register is aliased across 1024-bytes region */ + n = ((words <= 1024) ? words : 1024); + memcpy ((void *)io_vaddr, p, n); + } + } + else /* standard Linux case: use __raw_writew for portability */ + { + while (words--) + { + __raw_writew (*vbuf, io_vaddr); + vbuf++; + } + } +} + + + +/*-----------------------------------------------------------------------* + * * + * d o c h b l k _ r e a d * + * * + * This routine transfers data from DiskOnChip H3 device to RAM. * + * * + * Parameters: * + * vbuf buffer to transfer data to * + * sectors number of 512-byte sectors to transfer * + * * + *-----------------------------------------------------------------------*/ + +int dochblk_read (void * vbuf, unsigned int sectors) +{ + flReadEvenNumberOfBytes ((DOCHFlash), DOCH_DATA_PORT_AREA, vbuf, ((sectors) << 9)); + return 0; +} + + + +/*-----------------------------------------------------------------------* + * * + * d o c h b l k _ w r i t e * + * * + * This routine transfers data from RAM to DiskOnChip H3 device. * + * * + * Parameters: * + * vbuf buffer to transfer data from * + * sectors number of 512-byte sectors to transfer * + * * + *-----------------------------------------------------------------------*/ + +int dochblk_write (void * vbuf, unsigned int sectors) +{ + flWriteEvenNumberOfBytes ((DOCHFlash), DOCH_DATA_PORT_AREA, vbuf, ((sectors) << 9)); + return 0; +} + + + + +void flSysfunInit ( void ) +{ + register int iSoc; + unsigned long win_size; /* size of DiskOnChip window in bytes */ + + total_sems = 0; + + /* DiskOnChip H3 devices can be configured to use 8-, 32- or 128-KByte + * window; we assume the worst case here (128-KB). + */ + win_size = DOCH_MEM_WIN_SIZE_128KB /* or DOCH_MEM_WIN_SIZE_8KB */; + + for (iSoc = 0; iSoc < FL_SOCKETS; iSoc++) + TffsMapMem (&tffsInfo.sockets[iSoc], tffs_addr[iSoc], win_size); + + /* We are not doing 'resume' after previous power 'suspend', but rather + * a full scale board initialization, hence FALSE flag below. + */ + if( tffsarch_init(FALSE) == 0 ) + PrintkWarning("tffsarch_init error"); +} + + + +void LnxSysfunRelease ( void ) +{ + int i; + + for (i = 0; i < FL_SOCKETS; i++) + TffsUnmapMem (&tffsInfo.sockets[i]); + + total_sems = 0; + + TffsHWRelease (); +} + + + +/*-----------------------------------------------------------------------* + * * + * f l C r e a t e M u t e x * + * * + * Create mutex. . * + * * + * Parameters: * + * mutex ID of newly created sempahore will be stored here * + * * + * Returns: * + * flOK if successful otherwise respective error code * + * * + *-----------------------------------------------------------------------*/ + +FLStatus flCreateMutex (FLMutex * mutex) +{ + if (total_sems >= (sizeof(sems) / sizeof(sems[0]))) + { + PrintkError("flCreateMutex: error creating mutex"); + return flNotEnoughMemory; + } + + /* initialize next available semaphore to 'available' state */ + sema_init (&sems[total_sems], 1); + + *mutex = (FLMutex) total_sems++; + + return flOK; +} + + + +/*-----------------------------------------------------------------------* + * * + * f l T a k e M u t e x * + * * + * Called to aquire the mutex. * + * * + * Parameters: * + * mutex identifies mutex to release * + * * + * Returns: * + * always TRUE * + * * + *-----------------------------------------------------------------------*/ + +FLBoolean flTakeMutex (FLMutex * mutex) +{ + register struct semaphore * psem = &sems[ (int)(*mutex) ]; + + /* put caller to sleep until semaphore is available */ + if( down_interruptible(psem) != 0 ) + { + /* Semaphore still isn't available - down_interruptible() returned + * because caller was waken up by signal. We must abort TrueFFS call. + */ + return FALSE; + } + + /* semaphore has been taken; TrueFFS call can proceed now */ + return TRUE; +} + + + +/*-----------------------------------------------------------------------* + * * + * f l F r e e M u t e x * + * * + * Called to release the mutex. * + * * + * Parameters: * + * mutex identifies mutex to release * + * * + *-----------------------------------------------------------------------*/ + +void flFreeMutex (FLMutex * mutex) +{ + register struct semaphore * psem = &sems[ (int)(*mutex) ]; + + /* release semaphore */ + up (psem); +} + + + +/*-----------------------------------------------------------------------* + * * + * f l D e l e t e M u t e x * + * * + * Called to destroy the mutex and free all associated resources. * + * * + * Parameters: * + * mutex identifies mutex to destroy * + * * + *-----------------------------------------------------------------------*/ + +void flDeleteMutex (FLMutex * mutex) +{ + /* just in case some thread(s) are still sleeping on this semaphore */ + flFreeMutex (mutex); +} + + + + +/*-----------------------------------------------------------------------* + * * + * f l B u i l d G e o m e t r y * + * * + * This routine calculates cylinder/head/sector geometry based on the * + * number of sectors on the disk. * + * * + * Parameters: * + * sectors total sectors on disk * + * cyl pointer to number of cylinders * + * heads pointer to number of heads * + * sec_per_track pointer to number of sectors per track * + * oldFormat ignored * + * wirHandle ignored * + * * + *-----------------------------------------------------------------------*/ + +void flBuildGeometry ( unsigned long sectors, + unsigned long * cyl, + unsigned long * heads, + unsigned long * sec_per_track, + unsigned char oldFormat, + unsigned short wIrHandle ) +{ + DeviceInfo * pdisk; + register int i; + + for (i = 0; i < (sizeof(tffsInfo.ppDevices) / sizeof(tffsInfo.ppDevices[0])); i++) + { + if ((pdisk = tffsInfo.ppDevices[i]) == NULL) + return; + + /* The 'wIrHandle' argument is the internal TrueFFS handle which is + * different from TrueFFS handle stored in DeviceInfo.bHandle, and + * passed to TrueFFS API routines. + */ + if (pdisk->dwSize == sectors) /* was (pdisk->bHandle == wIrHandle) */ + { + if (cyl != NULL) *cyl = pdisk->wCyl; + if (heads != NULL) *heads = pdisk->bHead; + if (sec_per_track != NULL) *sec_per_track = pdisk->bSect; + + return; + } + } +} + + + + +/*-----------------------------------------------------------------------* + * * + * i r q _ w a i t _ t i m e d _ o u t * + * * + * This routine is called when DiskOnChip interrupt gets lost, and * + * watchdog timer gets activated. It prevents driver from hanging up in * + * such cases by posting a semaphore that socket's I/O thread is waiting * + * for. * + * * + * Parameters: * + * arg pointer to semaphore * + * * + *-----------------------------------------------------------------------*/ + +static +void irq_wait_timed_out ( unsigned long arg ) +{ + profiling[5]++; + + /* Since this routine is running, it means that DiskOnChip interrupt + * got lost (or delayed for too long). To prevent socket's I/O thread + * from hanging up, we wake up I/O thread here. + */ + complete ((struct completion *)arg); /* up ((struct semaphore *)arg); */ +} + + + + +/*-----------------------------------------------------------------------* + * * + * f l _ t f f s _ s l e e p * + * * + * This routine is called right after starting flash 'write' or 'erase' * + * operation on DiskOnChip. These operations usually take around 700 * + * ('write') or 3000 ('erase') microseconds to complete. This routine * + * might yield the CPU and cause task switch. * + * * + * Parameters: * + * handle TrueFFS handle (only lower 4 bits are used) * + * microseconds expected average duration of flash operation * + * * + *-----------------------------------------------------------------------*/ + +void fl_tffs_sleep ( unsigned int handle, + unsigned long microseconds ) +{ +#ifdef TFFS_USE_SLEEP + + int socNo = (int)(handle & 0xf); /* extract socket # from TrueFFS handle */ + + static int _counter = 0; + + if (tffsInfo.sockets[socNo].io_thread_state != 1) + { + /* DiskOnChip driver is being uninstalled, or power-suspended, or is + * power-resuming. In either of these cases, we want to process all + * outstanding I/O requests as quickly as possible; therefore we + * will not sleep. + */ + return; + } + + if (tffs_irq < 0) /* DiskOnChip R/B interrupts are not used */ + { + if (++_counter > tffs_skip_sleeps) + { + /* Once in a while (once in 'tffs_skip_sleeps' calls to this routine) + * we yield CPU and put DiskOnChip driver to sleep, to give chance + * to other tasks to run. Note that this negatively impacts + * DiskOnChip's 'write' performance. + */ + unsigned long jiffies_to_sleep = (HZ * microseconds) / 1000000; +#if 0 + if (jiffies_to_sleep == 0) + jiffies_to_sleep = 1; +#endif + /* yield CPU and sleep */ + set_current_state (TASK_INTERRUPTIBLE); + schedule_timeout (jiffies_to_sleep); + + _counter = 0; + } + else + { + /* TrueFFS will busy-poll DiskOnChip's status register to + * detect completion of flash 'write' and 'erase' operations. This + * improves DiskOnChip's 'write' performance, but also ties up CPU + * for extensive periods of time. + */ + return; + } + } + else /* yield CPU and sleep until waken up by DiskOnChip interrupt */ + { + struct timer_list watchdog_timer; + + profiling[0]++; + + /* To guard ourselves against stray DiskOnChip interrupts, + * we clear tffsInfo.sockets[socNo].wait_for_irq + * before enabling IRQ that DiskOnChip is nonnected to + */ + init_completion (&tffsInfo.sockets[socNo].wait_for_irq); /* sema_init (&tffsInfo.sockets[socNo].sleep_sem, 0); */ + + tffs_irq_enable (TRUE); + + /* To guard ourselves against the case when DiskOnChip interrupt + * will not be generated for some reason, or will get lost, we + * set watchdog timer to wake us up after 30 milliseconds. + */ + init_timer (&watchdog_timer); + watchdog_timer.function = irq_wait_timed_out; + watchdog_timer.data = (unsigned long) &tffsInfo.sockets[socNo].wait_for_irq /* &tffsInfo.sockets[socNo].sleep_sem */ ; + watchdog_timer.expires = jiffies + ((30 * HZ) / 1000); + add_timer (&watchdog_timer); + + /* sleep until DiskOnChip interrupt or watchdog timer wakes us up */ + wait_for_completion (&tffsInfo.sockets[socNo].wait_for_irq); /* down_interruptible (&tffsInfo.sockets[socNo].sleep_sem); */ + + tffs_irq_disable (TRUE); + + /* no longer need watchdog timer */ + del_timer_sync (&watchdog_timer); + } +#endif /* TFFS_USE_SLEEP */ +} + + + + +/*-----------------------------------------------------------------------* + * * + * d o c h _ s l e e p * + * * + * This routine is called numerous times during DiskOnChip H3 'write' * + * operations. * + * * + * Parameters: * + * sock socket # (zero-based) * + * microseconds expected average duration of flash operation * + * * + *-----------------------------------------------------------------------*/ + +void doch_sleep ( unsigned int soc, + unsigned long microseconds ) +{ + extern int write_requests; + static int __write_requests = 0; + + /* If DiskOnChip IRQ is enabled, or if 'tffs_skip_sleeps' set to yeild + * CPU often, we yield CPU. + */ + if (tffs_irq >= 0) + { + fl_tffs_sleep (soc, microseconds); + } + else + { + /* DiskOnChip IRQ is disabled. We yield CPU according to + * 'tffs_skip_sleep' setting, making sure that we do yield CPU + * at least once per I/O 'write' request. + */ + if ((tffs_skip_sleeps >= 100) || (write_requests != __write_requests)) + { + fl_tffs_sleep (soc, microseconds); + } + __write_requests = write_requests; + } +} diff -urN linux-2.6.30.4-orig/drivers/block/tffs/flsystem.h linux-2.6.30.4/drivers/block/tffs/flsystem.h --- linux-2.6.30.4-orig/drivers/block/tffs/flsystem.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/flsystem.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,164 @@ +/****************************************************************************** + * * + * Project: DOC Driver for Linux 2.6 Block device driver for mDOC H3 family * + * of devices under Linux kernel 2.6. * + * * + * Version: 1.0 * + * Email questions to: oemsupport@sandisk.com * + * Copyright (C) SanDisk IL Ltd. 1995 - 2007 * + * SanDisk IL Ltd., 7 Atir Yeda Street, Kfar Saba 44425, Israel * + * * + ****************************************************************************** + * * + * 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 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, which is set forth in the readme.txt file. * + * 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., 51 * + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + * * + * This License does not grant you any right to use the trademarks, service * + * marks or logos of SanDisk IL Ltd. or SanDisk Corporation. * + * Subject to the foregoing, SanDisk IL Ltd., for itself and on behalf of its * + * licensors, hereby reserves all intellectual property rights in the program,* + * except for the rights expressly granted in this License. * + * * + ******************************************************************************/ + +/* + * $Log$ + */ + + +#ifndef FLSYSTEM_H +#define FLSYSTEM_H + +#include "flcustom.h" +#include "tffsarch.h" + +#include +#include +#include +#ifdef __KERNEL__ +# include +#endif + +#define NAMING_CONVENTION /* don't change me */ +#define TFFS_DLL_API +#define FL_PACKED_STRUCTURES __attribute__ ((packed)) +#ifndef TRUE +# define TRUE 1 +#endif +#ifndef FALSE +# define FALSE 0 +#endif + +#define FAR_LEVEL 0 +#define FLMutex int + +#ifndef FL_IOCTL_START +# define FL_IOCTL_LNX 0 /* don't change */ +# define FL_IOCTL_START 1 /* don't change */ +#endif + + +/* + * "yield CPU and sleep" implementation for G4/G3/H1 DiskOnChip devices + */ +#define FL_TFFS_SLEEP(handle,microseconds) fl_tffs_sleep((unsigned int)(handle),(microseconds)) +extern void fl_tffs_sleep (unsigned int handle, unsigned long microseconds); + + +/* + * "yield CPU and sleep" implementation for H3 DiskOnChip devices + */ +#define DOCH_SLEEP(soc,dev,microseconds) doch_sleep((soc),(microseconds)) +extern void doch_sleep (unsigned int soc, unsigned long microseconds); + + +/* + * macros for printing debug messages + */ +#define DBG_PRINT_FLOW(zone,str) do { if(fl_debug & 4) {LnxTffsPrint(str);} } while(0) +#define DBG_PRINT_FLOW_PRM(zone,str) do { if(fl_debug & 4) {LnxTffsPrint str; } } while(0) +#define DBG_PRINT_WRN(zone,str) do { if(fl_debug & 2) {LnxTffsPrint(str);} } while(0) +#define DBG_PRINT_WRN_PRM(zone,str) do { if(fl_debug & 2) {LnxTffsPrint str; } } while(0) +#define DBG_PRINT_ERR(zone,str) do { if(fl_debug & 1) {LnxTffsPrint(str);} } while(0) +#define DBG_PRINT_ERR_PRM(zone,str) do { if(fl_debug & 1) {LnxTffsPrint str; } } while(0) +extern int LnxTffsPrint (const char *fmt, ...); +extern int fl_debug; + +/* + * dynamic memory allocation/freeing + */ +#define FL_MALLOC TffsMalloc +#define FL_FREE TffsFree +extern void * TffsMalloc (unsigned long size); +extern void TffsFree (void *vptr); + +/* + * Macro DOCH_SYS_FUNC_RELEASE is invoked when rmmod is called + */ +#define DOCH_SYS_FUNC_RELEASE LnxSysfunRelease() +extern void LnxSysfunRelease (void); + +/* + * pointer manupulation macros + */ +#define physicalToPointer(paddr,size,drive) ((void *) (paddr)) +#define addToFarPointer(ptr,val) ((void *) ((unsigned char *) (ptr) + (val))) +#define freePointer(ptr,size) /* do nothing */ + +/* + * macros tffscpy/tffscmp/tffsset are used with RAM buffers only + */ +#define tffscpy memcpy +#define tffscmp memcmp +#define tffsset memset + +/* + * macros for writing byte/short word/long word to I/O memory + */ +#define FLWRITE_IO_BYTE(val,addr) writeb((unsigned char) (val),(volatile unsigned char *)(addr)) +#define FLWRITE_IO_WORD(val,addr) __raw_writew((unsigned short)(val),(addr)) +#define FLWRITE_IO_DWORD(val,addr) __raw_writel((unsigned long) (val),(addr)) + +/* + * macros for reading byte/short word/long word from I/O memory + */ +#define FLREAD_IO_BYTE(addr) readb((volatile unsigned char*) (addr)) +#define FLREAD_IO_WORD(addr) __raw_readw(addr) +#define FLREAD_IO_DWORD(addr) __raw_readl(addr) + +/* + * macros for transferring data blocks to I/O memory + */ +#define TFFSCPY_FROM_IO(dest,src,cnt) memcpy_fromio((dest),(void*)(src),(cnt)) +#define TFFSCPY_FROM_IO_8_BITS TFFSCPY_FROM_IO +#define TFFSCPY_FROM_IO_16_BITS TFFSCPY_FROM_IO + +/* + * macros for transferring data blocks from I/O memory + */ +#define TFFSCPY_TO_IO(dest,src,cnt) memcpy_toio((void*)(dest),(src),(cnt)) +#define TFFSCPY_TO_IO_8_BITS TFFSCPY_TO_IO +#define TFFSCPY_TO_IO_16_BITS TFFSCPY_TO_IO + +/* + * macros for memset-like operations on I/O memory + */ +#define TFFSSET_IO(dest,val,cnt) memset_io((void*)(dest),(val),(cnt)) +#define TFFSSET_IO_8_BITS TFFSSET_IO +#define TFFSSET_IO_16_BITS TFFSSET_IO + + +extern int tffs_irq; +extern void tffs_irq_enable (int lock); +extern void tffs_irq_disable (int lock); + + +#endif /* FLSYSTEM_H */ diff -urN linux-2.6.30.4-orig/drivers/block/tffs/flsystyp.h linux-2.6.30.4/drivers/block/tffs/flsystyp.h --- linux-2.6.30.4-orig/drivers/block/tffs/flsystyp.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/flsystyp.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,96 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/version 6.3-up/BDK/src/flsystyp.h-arc $ + * + * Rev 1.14 Oct 22 2007 11:34:54 einat.avidan + * update copyrights header + */ + +/***************************************************************************** +* File Header * +* ----------- * +* Name : flsystyp.h * +* * +* Description : System defintions and types required for the implementation * +* of the system customization routines. * +* * +*****************************************************************************/ + +#ifndef FLSYSTYPE_H +#define FLSYSTYPE_H + + +#include "_common.h" +#include "flsystem.h" + +/* Boolean constants */ +#ifndef FALSE +#define FALSE 0 +#endif /* FALSE */ +#ifndef TRUE +#define TRUE 1 +#endif /* TRUE */ + + +/* Zones for debug printing */ + +#define FLZONE_NONE 0 +#define FLZONE_MTD 0x0001 +#define FLZONE_BDK 0x0002 +#define FLZONE_TL 0x0004 +#define FLZONE_BLKDEV 0x0008 +#define FLZONE_FORMAT 0x0010 +#define FLZONE_FS 0x0020 +#define FLZONE_SOCKET 0x0040 +#define FLZONE_IOCTL 0x0080 +#define FLZONE_PROD 0x0100 +#define FLZONE_STATISTICS 0x0200 +#define FLZONE_UTIL 0x0400 +#define FLZONE_PARA 0x0800 +#define FLZONE_ABS 0x1000 +#define FLZONE_ATA 0x2000 +#define FLZONE_API 0x4000 +#define FLZONE_FULL 0xffff + +#endif /* FLSYSTYPE_H */ diff -urN linux-2.6.30.4-orig/drivers/block/tffs/_fltl.h linux-2.6.30.4/drivers/block/tffs/_fltl.h --- linux-2.6.30.4-orig/drivers/block/tffs/_fltl.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/_fltl.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,172 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/3/common/_fltl.h-arc $ + * + * Rev 1.9 Oct 22 2007 11:34:46 einat.avidan + * update copyrights header + * + * Rev 1.8 Feb 28 2007 10:49:44 einat.avidan + * removed unnecessary decleration + * + * Rev 1.7 Oct 09 2006 14:03:52 yaniv.iarovici + * Removed legacy devices related code and definitions + * + * Rev 1.6 Sep 11 2006 13:45:10 yaniv.iarovici + * Legal header added + * + * Rev 1.5 Aug 09 2006 16:52:46 Polina.Marimont + * initial for DOC Driver 1.0 + */ + +#ifndef _FLTL_H +#define _FLTL_H + +typedef struct { + SectorNo sectorsInVolume; + FLDword bootAreaSize; + FLDword eraseCycles; + FLDword tlUnitBits; +} TLInfo; + + +/* Defragment modes types */ +#define FL_FAST_SPACE 0 +#define FL_NORMAL_SPACE 1 + + + +typedef struct tTLrec TLrec; /* Defined by translation layer */ + + +struct tTL { + TLrec *rec; + FLByte partitionNo; + FLByte socketNo; + + /* information is necessary for hard-disk TL implementation */ + FLWord cylinders; + FLWord heads; + FLWord sectorsPerTrack; + /* they should not be concealed in TL->rec field: when the media is formatted + it would be best if geometry written in BPB would match actual disk geometry */ + + /* information necessary to support fast+normal geometry */ + FLDword fastAreaSectors; + FLWord fastArea_SectorsInUnit_Bits; + FLWord normalArea_SectorsInUnit_Bits; + FLWord riskZoneSectors; /* largest of fast and normal risk zones */ + FLWord recommendedSectorsInCluster; /* or just call it sectorsInPage (also largest) */ + /* there is no need to hide these vars via "recommendedClusterInfo" : + they are not used by TL itself. BTW, getTLinfo is not necessary for same reason */ + + void FAR1* progressCallback; + +#ifndef FL_NEW_MAPSECTOR + const void FAR0 *(*mapSector)(TLrec *, SectorNo sectorNo, CardAddress *physAddr); +#else + FLStatus (*mapSector)(TLrec *, SectorNo sectorNo, void * *retBuffer); +#endif + + FLStatus (*writeSector)(TLrec *, SectorNo sectorNo, void FAR1 *fromAddress); + + FLStatus (*writeMultiSector)(TLrec *, SectorNo sectorNo, void FAR1 *fromAddress,SectorNo sectorCount); + FLStatus (*readSectors)(TLrec *, SectorNo sectorNo, void FAR1 *dest,SectorNo sectorCount); + + FLStatus (*deleteSector)(TLrec *, SectorNo sectorNo, SectorNo noOfSectors); + FLStatus (*tlSetBusy)(TLrec *, FLBoolean); + void (*dismount)(TLrec *); + FLStatus (*defragment)(TLrec *, FLSDword FAR2 *sectorsNeeded, FLDword normalSpace); + FLStatus (*checkVolume)(TLrec *); + SectorNo (*sectorsInVolume)(TLrec *); + FLStatus (*getTLInfo)(TLrec *, TLInfo *tlInfo); + void (*recommendedClusterInfo)(TLrec *, FLDword *sectorsPerCluster, FLDword *clusterAlignment); + + FLStatus (*readBBT)(TLrec *, CardAddress FAR1 * buf, FLSDword FAR2 * mediaSize, unsigned FAR2 * noOfBB); + + FLStatus (*notifyChange)(TLrec *, void FAR1 * reserved, FLEnvVars variableType , FLDword value); + FLStatus (*completeOperation)(TLrec *); + + FLDword (* getLastMappedSectorAddress)(TLrec *); /* use after mapSector */ + FLStatus (* ensureFreeSectorsInUnit)(TLrec *, FLWord wVirtualUnit, FLWord * wFreeSectorsRequired); + FLStatus (*secureDeleteSector)(TLrec *, SectorNo sectorNo, SectorNo noOfSectors, FLBoolean secureOperation); +}; + + + +/* The address of this, if returned from map, denotes a data error */ +#ifndef FL_NEW_MAPSECTOR +/* extern FLStatus dataErrorObject; +#define dataErrorToken ((void FAR0 *) &dataErrorObject) */ + +#define dataErrorToken ((void FAR0 *) 0xFFFFFFFF) +/* temporary - should not be necessary with new mapSector +old method (address of dataErrorObject) is not translatable across BD-FS split +or translatable with added code/complexity */ +#endif /* FL_NEW_MAPSECTOR */ + +#ifdef FLFLASH_H +/* Translation layer registration information */ + +extern int noOfTLs; /* No. of translation layers actually registered */ + +typedef struct { + FLStatus (*mountRoutine) (unsigned volNo, TL *tl, FLFlash *flash, FLFlash **volForCallback); + FLStatus (*formatRoutine) (unsigned volNo, TLFormatParams *deviceFormatParams, FLFlash *flash); + FLStatus (*preMountRoutine)(FLFunctionNo callType, IOreq FAR2* ioreq ,FLFlash* flash,FLStatus* status); +} TLentry; + +extern FLStatus noFormat (unsigned volNo, TLFormatParams *formatParams, FLFlash *flash); +extern FLStatus flMount(unsigned volNo, unsigned socketNo,TL *, FLBoolean useFilters , FLFlash *flash); +extern FLStatus flPreMount(FLFunctionNo callType, IOreq FAR2* ioreq , FLFlash *flash); +extern unsigned noOfDrives; + +#ifdef FL_FORMAT_VOLUME +extern FLStatus flFormat(unsigned volNo, TLFormatParams *formatParams, FLFlash * flash); +#endif /* FL_FORMAT_VOLUME */ + +#endif /* FLFLASH_H */ + +#endif /* FLTL_H */ + + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/fltl.h linux-2.6.30.4/drivers/block/tffs/fltl.h --- linux-2.6.30.4-orig/drivers/block/tffs/fltl.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/fltl.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,122 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ + +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/3/common/fltl.h-arc $ + * + * Rev 1.9 Oct 22 2007 11:34:54 einat.avidan + * update copyrights header + * + * Rev 1.8 Sep 11 2006 13:45:24 yaniv.iarovici + * Legal header added + * + * Rev 1.7 Aug 09 2006 16:52:52 Polina.Marimont + * initial for DOC Driver 1.0 + */ + +#ifndef FLTL_H +#define FLTL_H + +#include "flbase.h" +#include "flstruct.h" + + +typedef struct tTL TL; + +/*----------------------------------------------------------*/ +/* Format Parameters record passed to the translation layer */ +/*----------------------------------------------------------*/ + +typedef struct { + + /* Global device info */ + + FLByte percentUse; + + FLByte noOfBDTLPartitions; + + FLByte noOfBinaryPartitions; + + BDTLPartitionFormatParams3 FAR2* BDTLPartitionInfo; + + BinaryPartitionFormatParams3 FAR2* binaryPartitionInfo; + + FLDword flags; + + /* First volume info */ + + FLByte protectionKey[8]; + + FLByte protectionType; + + FLByte noOfSpareUnits; + + /* Special features */ + + FLByte cascadedDeviceNo; + + FLByte noOfCascadedDevices; + + FLProgressCallback progressCallback; + + FLDword osakVersion; + + /* None DiskOnChip parameters */ + + FLSDword bootImageLen; + + FLSDword dataPartitionLen; + + FLDword vmAddressingLimit; + + FLWord embeddedCISlength; + + FLByte FAR1 * embeddedCIS; + +} TLFormatParams; + +#include "_fltl.h" + +#endif /* FLTL_H */ + + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/geometry.c linux-2.6.30.4/drivers/block/tffs/geometry.c --- linux-2.6.30.4-orig/drivers/block/tffs/geometry.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/geometry.c 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,132 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/3/common/geometry.c-arc $ + * + * Rev 1.6 Oct 22 2007 11:34:54 einat.avidan + * update copyrights header + * + * Rev 1.5 Sep 11 2006 13:45:26 yaniv.iarovici + * Legal header added + * + * Rev 1.4 Aug 09 2006 16:52:52 Polina.Marimont + * initial for DOC Driver 1.0 + */ + +#include "flbase.h" + +/*----------------------------------------------------------------------*/ +/* f l B u i l d G e o m e t r y */ +/* */ +/* Get C/H/S information of the disk according to number of sectors. */ +/* */ +/* Parameters: */ +/* capacity : Number of Sectors in Volume */ +/* cylinders : Pointer to Number of Cylinders */ +/* heads : Pointer to Number of Heads */ +/* sectors : Pointer to Number of Sectors per Track */ +/* oldFormat : True for one sector per culoster */ +/* wIrHandle : Handle of the disk partition to check */ +/* */ +/*----------------------------------------------------------------------*/ + +#ifdef __cplusplus +extern "C" +#endif /* __cplusplus */ + +TFFS_DLL_API void NAMING_CONVENTION flBuildGeometry(FLDword capacity, FLDword FAR2 *cylinders, + FLDword FAR2 *heads, FLDword FAR2 *sectors, FLBoolean oldFormat, FLWord wIrHandle) +{ + FLDword temp; + FLDword orgCapacity = capacity; + +START_BUILD_GEOMETRY_ROUTINE: + + *cylinders = 1024; /* Set number of cylinders to max value */ + + if (oldFormat == TRUE) + { + *sectors = 62L; /* Max out number of sectors per track */ + temp = (*cylinders) * (*sectors); /* Compute divisor for heads */ + (*heads) = capacity / temp; /* Compute value for number of heads */ + if (capacity % temp) { /* If no remainder, done! */ + (*heads)++; /* Else, increment number of heads */ + temp = (*cylinders) * (*heads); /* Compute divisor for sectors */ + (*sectors) = capacity / temp; /* Compute value for sectors per track */ + if (capacity % temp) { /* If no remainder, done! */ + (*sectors)++; /* Else, increment number of sectors */ + temp = (*heads) * (*sectors); /* Compute divisor for cylinders */ + (*cylinders) = capacity / temp; /* Compute number of cylinders */ + } + } + } + else + { + *heads = 16L; /* Max out number of heads */ + temp = (*cylinders) * (*heads); /* Compute divisor for heads */ + *sectors = capacity / temp; /* Compute value for sectors per track */ + while (*sectors > 0x3f ){ /* While number of sectors too big */ + *heads *= 2; /* use one more head */ + temp = (*cylinders) * (*heads); /* Recompute divisor for heads */ + *sectors = capacity / temp; /* Recompute sectors per track */ + } + if (capacity % temp) { /* If no remainder, done! */ + (*sectors)++; /* Else, increment number of sectors */ + temp = (*cylinders) * (*sectors); /* Compute divisor for heads */ + *heads = capacity / temp; /* Compute value for heads */ + if (capacity % temp) { /* If no remainder, done! */ + (*heads)++; /* Else, increment number of heads */ + temp = (*heads) * (*sectors); /* Compute divisor for cylinders */ + *cylinders = (FLDword)(capacity / temp); /* Compute number of cylinders */ + } + } + } + /* Make sure some free sectors are left between C*H*S and TL sectors */ + if(orgCapacity == (*sectors) * (*heads) * (*cylinders)) + { + capacity--; + goto START_BUILD_GEOMETRY_ROUTINE; + } +} + +/*----------------------------------------------------------------------*/ diff -urN linux-2.6.30.4-orig/drivers/block/tffs/hal_nor.c linux-2.6.30.4/drivers/block/tffs/hal_nor.c --- linux-2.6.30.4-orig/drivers/block/tffs/hal_nor.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/hal_nor.c 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,464 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ + +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Test for 7.x/src/H3/hal_nor.c-arc $ + * + * Rev 1.25 Oct 22 2007 11:34:54 einat.avidan + * update copyrights header + * + * Rev 1.24 Mar 11 2007 16:41:20 einat.avidan + * bug fix: working on x86 requires read buffer not to be paged out + * replace the former solution (access to the begining and the end of the buffer under NO_INIT_MMU_PAGES compilation flag) + * with full solution: usage of a buffer that is locked on RAM + * + * Rev 1.23 Sep 11 2006 13:45:26 yaniv.iarovici + * Legal header added + * + * Rev 1.22 Aug 09 2006 17:26:56 Polina.Marimont + * initial for DOC Driver 1.0 + * + */ + +/* + * includes + */ +#include "flbase.h" +#include "hal_nor.h" +#include "doch_sys.h" +#include "doch_ata.h" + +#ifdef FL_MIGRATION_VERSION +#include "docsys.h" +#endif /*FL_MIGRATION_VERSION*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Externals + */ +extern FLDword gAccessLayerType; + +#ifdef __cplusplus +} +#endif + + +#ifdef DOCH_USE_FUNC + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Externals + */ +extern FLDword gAccessLayerType; + +/* + * global vars + */ + +/****************************************************************************** + * * + * d o c h _ s y s _ i n i t * + * * + * Initialize BSP specific part of DOCH driver. * + * * + * Parameters : * + * socketNo : Socket # (0...DOCH_MAX_SOCKETS-1) * + * * + * Returns : * + * 0 if success, otherwise respective error code. * + * * + ******************************************************************************/ + +DOCH_Error hal_init_nor ( FLSNative socketNo) +{ + DOCH_Socket* pdev; + DOCH_get_socket(pdev, socketNo); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Register access layer routines*/ + pdev->halRoutines.hal_get_ata_reg = hal_get_ata_reg_nor; + pdev->halRoutines.hal_set_ata_reg = hal_set_ata_reg_nor; + pdev->halRoutines.hal_get_ctrl_reg = hal_get_ctrl_reg_nor; + pdev->halRoutines.hal_set_ctrl_reg = hal_set_ctrl_reg_nor; + pdev->halRoutines.hal_blk_read = hal_blk_read_nor; + pdev->halRoutines.hal_blk_write = hal_blk_write_nor; + pdev->halRoutines.hal_doch_release = doch_sys_release_nor; + + gAccessLayerType = DOCH_AL_NOR; + + return DOCH_OK; +} + +/*********************************************************/ +/* Function name : doch_sys_release_nor*/ +/* Description : */ +/* Return type : */ +/* Argument : int socketNo*/ +/*********************************************************/ +FLSNative doch_sys_release_nor(int socketNo) +{ + return flOK; +} + +/****************************************************************************** + * * + * d o c h_ s y s _ g e t _ r e g X * + * * + * Reads DOCH register. * + * * + * Parameters : * + * base : pointer to the base of DOCH register set * + * reg : ATA register number * + * * + * Returns : * + * value of specified register * + * * + ******************************************************************************/ +FLByte hal_get_ata_reg_nor(volatile FLByte *base, FLSNative reg) +{ + volatile FLWord* vPtr = (volatile FLWord*)addToFarPointer(base, (reg<<1) + DOCH_CONT_REG_AREA); + FLWord val = DOCHREAD_IO_WORD(vPtr); + +#ifdef DOCH_BIG_ENDIAN + return (FLByte)(val>>8); /*Value is returned in the higher byte*/ +#else /*DOCH_BIG_ENDIAN*/ + return (FLByte)(val); +#endif /*DOCH_BIG_ENDIAN*/ +} + +FLWord hal_get_ctrl_reg_nor ( volatile FLByte * base, + FLSNative reg ) +{ + volatile FLWord* vPtr = (volatile FLWord*)addToFarPointer(base, reg); + FLWord regVal = DOCHREAD_IO_WORD(vPtr); + +#ifdef DOCH_BIG_ENDIAN + return ((regVal<<8) | (regVal>>8)); /*Swap high/low bytes*/ +#else /*DOCH_BIG_ENDIAN*/ + return regVal; +#endif /*DOCH_BIG_ENDIAN*/ +} + +/****************************************************************************** + * * + * d o c h _ s y s _ s e t _ r e g X * + * * + * Writes DOCH register. * + * * + * Parameters : * + * base : pointer to the base of DOCH register set * + * reg : ATA register number * + * val : value to write to register * + * * + * Returns : * + * value of specified register * + * * + ******************************************************************************/ + +void hal_set_ata_reg_nor( volatile FLByte * base, + FLSNative reg, + FLNative val ) +{ + volatile FLWord* vPtr = (volatile FLWord*)addToFarPointer(base, (reg<<1) + DOCH_CONT_REG_AREA); + +#ifdef DOCH_BIG_ENDIAN + val = ((val>>8) | (val<<8)); +#endif /*DOCH_BIG_ENDIAN*/ + + DOCHWRITE_IO_WORD((FLWord)val, vPtr); +} + +void hal_set_ctrl_reg_nor ( volatile FLByte * base, + FLSNative reg, + FLNative val ) +{ +#ifdef DOCH_BIG_ENDIAN + val = ((val>>8) | (val<<8)); +#endif /*DOCH_BIG_ENDIAN*/ + + DOCHWRITE_IO_WORD((FLWord)val, (base + reg)); +} + +/****************************************************************************** + * * + * b l k _ r e a d_ u s i n g _ d a t a _ r e g * + * * + * Read specified # of bytes through the ATA data register * + * * + * Parameters : * + * base : pointer to the base of DOCH register set * + * buf : buffer to write from * + * bytes : number of bytes to write * + * * + * Returns : * + * NONE * + * * + ******************************************************************************/ +void blk_read_using_data_reg ( volatile FLByte * base, + FLByte * buf, + FLSNative bytes ) +{ + register FLWord * buf16 ; + register FLSNative max; + + buf16 = (FLWord *) buf; + max = (FLSNative)buf + bytes; + + /* retrieve data */ + for (; (FLSNative)buf16 < max; buf16+=8) + { + buf16[0] = DOCHREAD_IO_WORD(base); + buf16[1] = DOCHREAD_IO_WORD(base); + buf16[2] = DOCHREAD_IO_WORD(base); + buf16[3] = DOCHREAD_IO_WORD(base); + buf16[4] = DOCHREAD_IO_WORD(base); + buf16[5] = DOCHREAD_IO_WORD(base); + buf16[6] = DOCHREAD_IO_WORD(base); + buf16[7] = DOCHREAD_IO_WORD(base); + } +} + +/****************************************************************************** + * * + * h a l _ b l k _ r e a d _ n o r * + * * + * Read 'sectors' sectors from DOCH * + * * + * Parameters : * + * base : pointer to the base of DOCH register set * + * dest : buffer to read to * + * sectors : number of sectors to read * + * * + * Returns : * + * always zero (success) * + * * + ******************************************************************************/ + +FLSNative hal_blk_read_nor ( volatile FLByte * base, + FLByte * dest, + FLSNative sectors ) +{ + volatile FLWord FAR0 * swin = (volatile FLWord FAR0 *)(addToFarPointer(base, DOCH_DATA_PORT_AREA)); + FLSNative count = sectors<>8); + dest[i++] = (FLByte)tmp; +#else + dest[i++] = (FLByte)tmp; + dest[i++] = (FLByte)(tmp>>8); +#endif /* DOCH_BIG_ENDIAN */ + } + } + else + { /* mainstream case */ + /* Some memcpy implementations from none 4 bytes aligned destination + * buffer may use a for loop of single byte calls to the first 2 + * bytes. This implementation may be good for RAM, but will be + * problematic to 16bit DiskOnChip that does not have a BHE signal. + * so if the buffer is not dword aligned we would not perform memcpy */ + + if (((FLDword)dest&0x3)==0) + { + DOCHCPY_FROM_IO_16_BITS( (volatile byte *)swin, dest, count ); + } + else + { /* read in short words */ + for (i = 0, count = count >> 1; i < (int)count; i++) + ((FLWord FAR1 *)dest)[i] = DOCHREAD_IO_WORD(swin); + } + } +#ifndef FL_NO_PF_PROTECTED_READ_MEM + tffscpy(OrigDest,protectedBuffer,count); +#endif /* FL_NO_PF_PROTECTED_READ_MEM */ + + return 0; +} + +/****************************************************************************** + * * + * b l k _ w r i t e _ u s i n g _ d a t a _ r e g * + * * + * Write specified # of bytes through the ATA data register * + * * + * Parameters : * + * base : pointer to the base of DOCH register set * + * buf : buffer to write from * + * bytes : number of bytes to write * + * * + * Returns : * + * NONE * + * * + ******************************************************************************/ +void blk_write_using_data_reg ( volatile FLByte * base, + FLByte * buf, + FLSNative bytes ) +{ + volatile FLWord * reg16 = (FLWord*)base; + register FLWord * buf16 ; + register FLSNative max; + + buf16 = (FLWord *) buf; + max = (FLSNative)buf + bytes; + + /* write data */ + for (; (FLSNative)buf16 < max; buf16+=8) + { + DOCHWRITE_IO_WORD(((FLWord FAR1 *)buf16)[0],reg16); + DOCHWRITE_IO_WORD(((FLWord FAR1 *)buf16)[1],reg16); + DOCHWRITE_IO_WORD(((FLWord FAR1 *)buf16)[2],reg16); + DOCHWRITE_IO_WORD(((FLWord FAR1 *)buf16)[3],reg16); + DOCHWRITE_IO_WORD(((FLWord FAR1 *)buf16)[4],reg16); + DOCHWRITE_IO_WORD(((FLWord FAR1 *)buf16)[5],reg16); + DOCHWRITE_IO_WORD(((FLWord FAR1 *)buf16)[6],reg16); + DOCHWRITE_IO_WORD(((FLWord FAR1 *)buf16)[7],reg16); + } +} + +/****************************************************************************** + * * + * h a l _ b l k _ w r i t e _ n o r * + * * + * write 'sectors' sectors to DOCH * + * * + * Parameters : * + * base : pointer to the base of DOCH register set * + * src : buffer to write from * + * sectors : number of sectors to write * + * * + * Returns : * + * always zero (success) * + * * + ******************************************************************************/ + +FLSNative hal_blk_write_nor ( volatile FLByte * base, + FLByte * src, + FLSNative sectors ) +{ + volatile FLWord FAR0 * swin = (volatile FLWord FAR0 *)addToFarPointer(base, DOCH_DATA_PORT_AREA); + FLSNative count = sectors<> 1; i < (int)count; i++) + /* while incrementing buffer offset */ + /* but do not increament DiskOnChip offset */ + DOCHWRITE_IO_WORD(((FLWord FAR1 *)src)[i],swin); + } + } + return 0; +} + + +#ifdef __cplusplus +} +#endif + +#else /*DOCH_USE_FUNC*/ + +DOCH_Error hal_init_nor_noFunc ( FLSNative socketNo) +{ + gAccessLayerType = DOCH_AL_NOR; + + return DOCH_OK; +} + +#endif /*DOCH_USE_FUNC*/ + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/hal_nor.h linux-2.6.30.4/drivers/block/tffs/hal_nor.h --- linux-2.6.30.4-orig/drivers/block/tffs/hal_nor.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/hal_nor.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,91 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Test for 7.x/src/H3/hal_nor.h-arc $ + * + * Rev 1.17 Oct 22 2007 11:34:54 einat.avidan + * update copyrights header + * + * Rev 1.16 Sep 11 2006 13:45:26 yaniv.iarovici + * Legal header added + * + * Rev 1.15 Aug 09 2006 17:26:56 Polina.Marimont + * initial for DOC Driver 1.0 + * + */ + +#ifndef DOCH_SYS_NOR_H +#define DOCH_SYS_NOR_H + +#include "flsystyp.h" +#include "doch_api.h" +#include "hib.h" + +#ifdef __cplusplus +extern "C" { +#endif + +DOCH_Error hal_init_nor (FLSNative socketNo); +DOCH_Error hal_init_nor_noFunc (FLSNative socketNo); +FLByte hal_get_ata_reg_nor (volatile FLByte *base, FLSNative reg); +void hal_set_ata_reg_nor (volatile FLByte *base, FLSNative reg, FLNative val); +FLWord hal_get_ctrl_reg_nor (volatile FLByte *base, FLSNative reg); +void hal_set_ctrl_reg_nor (volatile FLByte *base, FLSNative reg, FLNative val); +FLSNative hal_blk_read_nor (volatile FLByte *base, FLByte *buf, FLSNative sectors); +FLSNative hal_blk_write_nor (volatile FLByte *base, FLByte *buf, FLSNative sectors); +FLSNative doch_sys_release_nor (int socketNo); + +/*Default read.write routines, using the ATA data register*/ +void blk_read_using_data_reg ( volatile FLByte * base, + FLByte * buf, + FLSNative bytes ); + +void blk_write_using_data_reg ( volatile FLByte * base, + FLByte * buf, + FLSNative bytes ); + +#ifdef __cplusplus +} +#endif + +#endif /*DOCH_SYS_NOR_H*/ diff -urN linux-2.6.30.4-orig/drivers/block/tffs/hib.h linux-2.6.30.4/drivers/block/tffs/hib.h --- linux-2.6.30.4-orig/drivers/block/tffs/hib.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/hib.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,272 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/general storage/TrueFFS (7.x)/src/H3/Include/hib.h-arc $ + * + * Rev 1.24 Oct 22 2007 11:34:54 einat.avidan + * update copyrights header + * + * Rev 1.23 Oct 21 2007 10:46:04 Einat.Avidan + * optimization: save address of each Hib area instead of + * saving offset and core address (spare repetitive add commands) + * + * Rev 1.22 Sep 11 2006 13:45:26 yaniv.iarovici + * Legal header added + * + * Rev 1.21 Aug 09 2006 17:26:56 Polina.Marimont + * initial for DOC Driver 1.0 + * + */ + +#ifndef HIB_H +#define HIB_H + +/* HIB registers */ +/* ============= */ + +extern FLWord gMemWindowType; +extern FLDword gDochMemWinSize; + +extern FLWord gHibContRegAreaAddress; +extern FLWord gHibDataPortAreaAddress; +extern FLWord gHibConfigRegAreaAddress; + +/*Memory window type and size*/ +/*---------------------------*/ +/*Type*/ +#define MEM_WIN_8KB 0 +#define MEM_WIN_128KB 1 + +/*Size*/ +#define DOCH_MEM_WIN_SIZE (gDochMemWinSize) +#ifdef DOCH_32K_SLIDING_WINDOW + #define DOCH_MEM_WIN_SIZE_8KB 0x8000 /*32KB*/ + #define DOCH_MEM_WIN_SIZE_128KB 0x8000 /*32KB*/ +#else /*DOCH_32K_SLIDING_WINDOW*/ + #define DOCH_MEM_WIN_SIZE_8KB 0x2000 /*8KB*/ + #define DOCH_MEM_WIN_SIZE_128KB 0x20000 /*128KB*/ +#endif /*DOCH_32K_SLIDING_WINDOW*/ + +/*Register Areas*/ +/*--------------*/ + + +#define HIB_CORE_ADDRESS_8KB 0x0000 +#ifdef DOCH_32K_SLIDING_WINDOW + #define HIB_CORE_ADDRESS_128KB 0x0000 +#else /*DOCH_32K_SLIDING_WINDOW*/ + #define HIB_CORE_ADDRESS_128KB 0x8000 +#endif /*DOCH_32K_SLIDING_WINDOW*/ + +/*Area Address*/ +#ifndef DOCH_CONT_REG_AREA_ADDRESS + #define DOCH_CONT_REG_AREA_ADDRESS (gHibContRegAreaAddress) +#endif /*DOCH_CONT_REG_AREA_ADDRESS*/ + +#ifndef DOCH_DATA_PORT_AREA_ADDRESS + #define DOCH_DATA_PORT_AREA_ADDRESS (gHibDataPortAreaAddress) +#endif /*DOCH_DATA_PORT_AREA_ADDRESS*/ + +#ifndef DOCH_CONFIG_REG_AREA_ADDRESS + #define DOCH_CONFIG_REG_AREA_ADDRESS (gHibConfigRegAreaAddress) +#endif /*DOCH_CONFIG_REG_AREA_ADDRESS*/ + +/*8KB Offsets*/ +#define DOCH_CONT_REG_AREA_8KB_OFFSET 0x0800 +#define DOCH_DATA_PORT_AREA_8KB_OFFSET 0x1000 +#define DOCH_CONFIG_REG_AREA_8KB_OFFSET 0x1400 + +/*128KB Offsets*/ +#define DOCH_CONT_REG_AREA_128KB_OFFSET 0 +#define DOCH_DATA_PORT_AREA_128KB_OFFSET 0x0800 +#define DOCH_CONFIG_REG_AREA_128KB_OFFSET 0x1400 +#define DOCH_PRIMARY_SECONDARY_AREA_128KB_OFFSET 0x1800 + + +#define DOCH_CONT_REG_AREA DOCH_CONT_REG_AREA_ADDRESS +#define DOCH_DATA_PORT_AREA DOCH_DATA_PORT_AREA_ADDRESS +#define DOCH_CONFIG_REG_AREA DOCH_CONFIG_REG_AREA_ADDRESS + + +/* Control registers - offset is from DOCH_CONT_REG_AREA*/ +/*------------------------------------------------------*/ +#define DOCH_VERSION_REG (DOCH_CONT_REG_AREA + 0xC1A) +#define DOCH_LAST_ACCESS_ADDR_REG (DOCH_CONT_REG_AREA + 0xC1E) +#define DOCH_PAGED_RAM_CMD_REG (0x30) +#define DOCH_PAGED_RAM_SELECT_REG (0x70) +#define DOCH_PAGED_RAM_COTP_STAT_DL_REG (0x78) +#define DOCH_PAGED_RAM_COTP_SELECT_REG (0x7C) +#define DOCH_PAGED_RAM_UNIQUE_ID_DL (0x80) + +/* Host Configuration registers - offset is from DOCH_CONFIG_REG_AREA*/ +/*-------------------------------------------------------------------*/ +#define HIB_CHIPID1_REG (DOCH_CONFIG_REG_AREA) +#define HIB_BURST_WRITE_MODE_CTRL_REG (DOCH_CONFIG_REG_AREA + 0x02) +#define HIB_BURST_WRITE_MODE_EXIT_REG (DOCH_CONFIG_REG_AREA + 0x04) +#define HIB_DOWNLOAD_CONTROL_REG (DOCH_CONFIG_REG_AREA + 0x06) +#define HIB_IPL_CONTROL_REG (DOCH_CONFIG_REG_AREA + 0x08) +#define HIB_WARM_BOOT_REG (DOCH_CONFIG_REG_AREA + 0x0A) +#define HIB_POWER_DOWN_REG (DOCH_CONFIG_REG_AREA + 0x0C) +#define HIB_DMA_CTRL_REG (DOCH_CONFIG_REG_AREA + 0x0E) +#define HIB_SW_LOCK_REG (DOCH_CONFIG_REG_AREA + 0x10) +#define HIB_ENDIAN_CTRL_REG (DOCH_CONFIG_REG_AREA + 0x12) +#define HIB_OPERATION_MODE_REG (DOCH_CONFIG_REG_AREA + 0x14) +#define HIB_POWER_MODE_REG (DOCH_CONFIG_REG_AREA + 0x16) +#define HIB_DMA_NEGATION_REG (DOCH_CONFIG_REG_AREA + 0x18) +#define HIB_CHIPID2_REG (DOCH_CONFIG_REG_AREA + 0x22) +#define HIB_BURST_READ_MODE_CTRL_REG (DOCH_CONFIG_REG_AREA + 0x24) + + + + +/*Specific per-register values*/ +/*============================*/ +/*Burst Read/Write Mode Control Register*/ +#define HIB_BURST_HOLD_1_CLK 0x0000 +#define HIB_BURST_HOLD_2_CLK 0x2000 + +#define HIB_BURST_LEN_4_CYC 0x0000 +#define HIB_BURST_LEN_8_CYC 0x0800 +#define HIB_BURST_LEN_16_CYC 0x1000 +#define HIB_BURST_LEN_32_CYC 0x1800 + +#define HIB_BURST_DISABLE 0x0000 +#define HIB_BURST_ENABLE 0x0001 + +/*Download Control Register*/ +#define HIB_DOWNLOAD_COMPLETED 0x0000 +#define HIB_DOWNLOAD_IN_PROCESS 0x0001 + +/*IPL Control Register*/ +#define HIB_IPL_WRITE_DISABLE 0x0000 +#define HIB_IPL_WRITE_ENABLE 0x0001 + +#define HIB_IPL_NOT_READY_FOR_WRITE 0x0000 +#define HIB_IPL_READY_FOR_WRITE 0x0002 + +/*Warm Boot Register*/ +#define HIB_WARM_RST_POLARITY_LOW 0x0000 +#define HIB_WARM_RST_POLARITY_HIGH 0x0001 + +#define HIB_WARM_RST_BURST_ON 0x0000 +#define HIB_WARM_RST_BURST_NO_CHNG 0x0002 + +/*Power Down Register*/ +#define HIB_DPD_PIN_POLARITY_LOW 0x0000 +#define HIB_DPD_PIN_POLARITY_LOW 0x0000 + +#define HIB_DPD_PIN_DISABLE 0x0000 +#define HIB_DPD_PIN_ENABLE 0x0002 + +/*DMA Control Register*/ +#define HIB_DMA_REQ_DISABLE 0x0000 +#define HIB_DMA_REQ_ENABLE 0x0001 + +#define HIB_DMA_REQ_POL_HIGH 0x0000 +#define HIB_DMA_REQ_POL_LOW 0x0002 + +#define HIB_DMA_REQ_LEVEL 0x0000 +#define HIB_DMA_REQ_EDGE 0x0004 + +/*S/W Lock Register*/ +#define HIB_SW_LOCK_ON 0x0001 + +/*Endian Control Register*/ +#define HIB_END_SWAP_OFF 0x0000 +#define HIB_END_SWAP_ON 0x0101 + +/*Operation Mode Register*/ +#define HIB_NON_PIPE_ACCESS 0x00 +#define HIB_PIPE_ACCESS 0x01 + +#define HIB_NO_ADDR_SHIFT 0x00 +#define HIB_ADDR_SHIFT 0x02 + +/*Power Mode Register*/ +#define HIB_POWER_DOWN 0x0001 + +/*Paged RAM Command Register*/ +#define HIB_PAGED_RAM_ENABLE_SELECT 0x71 + +/*Paged RAM Select Register*/ +#define HIB_PAGED_RAM_SEQ 0x0080 + + +/*Folloing array is used to conserve every write to a configuration register. +The purpose is to enable reseting the device registers in case of power loss*/ +typedef struct { + FLWord wBurstWriteModeCtrl; + FLWord wIPLCtrl; + FLWord wPowerDown; + FLWord wDMACtrl; + FLWord wSWLock; + FLWord wEndianCtrl; + FLWord wEndianNegation; + FLWord wOperationMode; + FLWord wBurstReadModeCtrl; +} DOCH_ConfigRegsValue; + +typedef struct { + FLWord wBurstWriteModeCtrlSet; + FLWord wIPLCtrlSet; + FLWord wPowerDownSet; + FLWord wDMACtrlSet; + FLWord wSWLockSet; + FLWord wEndianCtrlSet; + FLWord wEndianNegationSet; + FLWord wOperationModeSet; + FLWord wBurstReadModeCtrlSet; +} DOCH_ConfigRegsSet; + +/* Changing device memory window size (8/128 KB)*/ +#define DOCH_PAGED_RAM_TIMEOUT 300000L +#define DOCH_READ_PAGED_RAM_DELAY 20 + +typedef enum { + DOCH_MEM_WIN_SIZE_8K = 0, + DOCH_MEM_WIN_SIZE_128K = 1, /*Regular, with no pull-downs on high address bits*/ + DOCH_MEM_WIN_SIZE_128K_SPECIAL = 2 /*Special, with pull-downs on high address bits*/ +} DOCH_MemWinSize; + +#endif /*HIB_H*/ + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/ioctl_example/ioctl-example.c linux-2.6.30.4/drivers/block/tffs/ioctl_example/ioctl-example.c --- linux-2.6.30.4-orig/drivers/block/tffs/ioctl_example/ioctl-example.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/ioctl_example/ioctl-example.c 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,791 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2006, msystems Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of msystems nor the names of its contributors may be */ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/******************************************************************************/ + + +#include +#include +#include +#include +#include +#include +#include +#include "tffsioct.h" + + + + +#define ALLOW_FORMATTING +#undef ALLOW_BDK +#define ALLOW_HW_PROTECTION + + +/* make TrueFFS ahndle out of socket and disk ## */ +#define mk_tffs_handle(socNo,diskNo) (((unsigned short)(socNo) & 0xf) | \ + (((unsigned int)(diskNo) << 4) & 0xf0)) + + +/* + * static routines + */ + +static int fl_ioctl_get_info (int fd); +static int fl_ioctl_defragment (int fd); +static int fl_ioctl_customer_id (int fd); + +#ifdef ALLOW_BDK + static int fl_ioctl_bdk_operation (int fd); +#endif + +static int hdio_getgeo (int fd); + +#ifdef ALLOW_FORMATTING + static int fl_ioctl_erase_bd (int fd); + static int fl_ioctl_flash_format (int fd); + static int fl_ioctl_flash_unformat (int fd); + static int fl_ioctl_mount_volume (int fd); +#endif + +#ifdef ALLOW_HW_PROTECTION + static int fl_ioctl_hw_protection (int fd, int ioctl_opcode); +#endif + + + + +int main ( int argc, char * argv[] ) +{ + int ioctl_opcode; + int flags; + int fd; + int rc = -1; + + /* check if devce name and IOCTL opcode are specified, and get IOCTL opcode */ + if ((argc < 3) || (sscanf(argv[2], "%d", &ioctl_opcode) != 1)) + { + fprintf (stderr, "Usage: ioctl-example \n"); + fprintf (stderr, "Example: ioctl-example /dev/tffsa 14\n"); + fprintf (stderr, "Accepted values for :\n"); + fprintf (stderr, " %d for FL_IOCTL_CUSTOMER_ID\n", FL_IOCTL_CUSTOMER_ID); + fprintf (stderr, " %d for FL_IOCTL_DEFRAGMENT\n", FL_IOCTL_DEFRAGMENT); + fprintf (stderr, " %d for FL_IOCTL_GET_INFO\n", FL_IOCTL_GET_INFO); +#ifdef ALLOW_BDK + fprintf (stderr, " %d for FL_IOCTL_BDK_OPERATION\n", FL_IOCTL_BDK_OPERATION); +#endif +#ifdef ALLOW_FORMATTING + fprintf (stderr, " %d for FL_IOCTL_MOUNT_VOLUME\n", FL_IOCTL_MOUNT_VOLUME); + fprintf (stderr, " %d for FL_IOCTL_ERASE_BD\n", FL_IOCTL_ERASE_BD); + fprintf (stderr, " %d for FL_IOCTL_FLASH_FORMAT\n", FL_IOCTL_FLASH_FORMAT); + fprintf (stderr, " %d for FL_IOCTL_FLASH_UNFORMAT\n", FL_IOCTL_FLASH_UNFORMAT); +#endif +#ifdef ALLOW_HW_PROTECTION + fprintf (stderr, " %d for FL_IOCTL_BDTL_HW_PROTECTION\n", FL_IOCTL_BDTL_HW_PROTECTION); +#endif + fprintf (stderr, " %d for HDIO_GETGEO\n", 0x0301 /* HDIO_GETGEO */); + exit (-1); + } + + /* open device */ + flags = ((ioctl_opcode == FL_IOCTL_GET_INFO) ? O_RDONLY : O_RDWR); + if((fd = open(argv[1], flags)) == -1) + { + perror ("Can't open device"); + exit (-1); + } + + /* issue IOCTL to device */ + switch (ioctl_opcode) + { + case FL_IOCTL_CUSTOMER_ID: + rc = fl_ioctl_customer_id (fd); + break; + + case FL_IOCTL_DEFRAGMENT: + rc = fl_ioctl_defragment (fd); + break; + + case FL_IOCTL_MOUNT_VOLUME: + rc = fl_ioctl_mount_volume (fd); + break; + + case FL_IOCTL_GET_INFO: + rc = fl_ioctl_get_info (fd); + break; + +#ifdef ALLOW_BDK + case FL_IOCTL_BDK_OPERATION: + rc = fl_ioctl_bdk_operation (fd); + break; +#endif + +#ifdef ALLOW_FORMATTING + case FL_IOCTL_ERASE_BD: + rc = fl_ioctl_erase_bd (fd); + break; + + case FL_IOCTL_FLASH_FORMAT: + rc = fl_ioctl_flash_format (fd); + break; + + case FL_IOCTL_FLASH_UNFORMAT: + rc = fl_ioctl_flash_unformat (fd); + break; +#endif + +#ifdef ALLOW_HW_PROTECTION + case FL_IOCTL_BDTL_HW_PROTECTION: + rc = fl_ioctl_hw_protection (fd, ioctl_opcode); + break; +#endif + + case 0x0301: /* HDIO_GETGEO */ + rc = hdio_getgeo (fd); + break; + + } + + close (fd); + + exit (rc); +} + + + + +static +int fl_ioctl_customer_id (int fd) +{ + flIOctlRecord ioctl_data; + flCustomerIdOutput out; + int rc; + + ioctl_data.inputRecord = NULL; /* no input record for this IOCTL */ + ioctl_data.outputRecord = &out; + rc = ioctl (fd, FL_IOCTL_CUSTOMER_ID, &ioctl_data); + if ((rc != 0) || (out.status != flOK)) + fprintf (stderr, "FL_IOCTL_CUSTOMER_ID IOCTL failed, error %d\n", out.status); + else + fprintf (stdout, "SUCCESS getting customer ID: 0x%x 0x%x 0x%x 0x%x\n", + out.id[0], out.id[1], out.id[2], out.id[3]); + return rc; +} + + + + +static +int fl_ioctl_defragment (int fd) +{ + flIOctlRecord ioctl_data; + flDefragInput in; + flDefragOutput out; + int rc; + + in.requiredNoOfSectors = -1; + + ioctl_data.inputRecord = ∈ + ioctl_data.outputRecord = &out; + rc = ioctl (fd, FL_IOCTL_DEFRAGMENT, &ioctl_data); + if ((rc == 0) && (out.status == flOK)) + fprintf (stdout, "free sectors after defragmentation: %ld\n", out.actualNoOfSectors); + + return rc; +} + + + + +static +int fl_ioctl_get_info (int fd) +{ + flIOctlRecord ioctl_data; + flDiskInfoOutput out; + int rc; + + ioctl_data.inputRecord = NULL; /* no input record for this IOCTL */ + ioctl_data.outputRecord = &out; + rc = ioctl (fd, FL_IOCTL_GET_INFO, &ioctl_data); + if ((rc != 0) || (out.status != flOK)) + fprintf (stderr, "FL_IOCTL_GET_INFO failed %d\n", out.status); + else + fprintf (stdout, "FL_IOCTL_GET_INFO reports %ld sectors\n", out.info.logicalSectors); + + return rc; +} + + + + +#ifdef ALLOW_FORMATTING + +static +int fl_ioctl_mount_volume (int fd) +{ + flIOctlRecord ioctl_data; + flMountInput in; + flOutputStatusRecord out; + int rc; + + ioctl_data.inputRecord = ∈ + ioctl_data.outputRecord = &out; + +#if 1 + in.type = FL_DISMOUNT; /* unmount disk */ +#else + in.type = FL_MOUNT; /* re-mount disk */ +#endif + + rc = ioctl (fd, FL_IOCTL_MOUNT_VOLUME, &ioctl_data); + if ((rc != 0) || (out.status != flOK)) + fprintf (stderr, "FL_IOCTL_MOUNT_VOLUME failed %d\n", out.status); + + return rc; +} + +#endif /* ALLOW_FORMATTING */ + + + + +#ifdef ALLOW_FORMATTING + +static +int fl_ioctl_erase_bd (int fd) +{ + flIOctlRecord ioctl_data; + int rc; + + /* unmount disk before formatting */ + { flMountInput in; + flOutputStatusRecord out; + + in.type = FL_DISMOUNT; + ioctl_data.inputRecord = ∈ + ioctl_data.outputRecord = &out; + rc = ioctl (fd, FL_IOCTL_MOUNT_VOLUME, &ioctl_data); + if ((rc != 0) || (out.status != flOK)) + fprintf (stderr, "FL_IOCTL_MOUNT_VOLUME/FL_DISMOUNT failed %d\n", out.status); + } + + /* re-format disk */ + { flEraseBDInput in; + flOutputStatusRecord out; + + in.dwFlags = 0; + ioctl_data.inputRecord = ∈ + ioctl_data.outputRecord = &out; + rc = ioctl (fd, FL_IOCTL_ERASE_BD, &ioctl_data); + if ((rc != 0) || (out.status != flOK)) + fprintf (stderr, "FL_IOCTL_ERASE_BD failed %d\n", out.status); + } + + /* re-mount disk */ + { flMountInput in; + flOutputStatusRecord out; + + in.type = FL_MOUNT; + ioctl_data.inputRecord = ∈ + ioctl_data.outputRecord = &out; + rc = ioctl (fd, FL_IOCTL_MOUNT_VOLUME, &ioctl_data); + if ((rc != 0) || (out.status != flOK)) + fprintf (stderr, "FL_IOCTL_MOUNT_VOLUME/FL_MOUNT failed %d\n", out.status); + } + + return rc; +} + +#endif /* ALLOW_FORMATTING */ + + + + +#ifdef ALLOW_FORMATTING + +static +int fl_ioctl_flash_format (int fd) +{ + flIOctlRecord ioctl_data; + flOutputStatusRecord out; + int rc; + + /* WARNING: You must send FL_IOCTL_MOUNT_VOLUME/FL_DISMOUNT call + * to all DiskOnChip disks (except for '/dev/tffsa') prior + * to calling this routine. You should not do that for + * /dev/tffsa - this routine must do it by itself. + */ + + /* send FL_IOCTL_MOUNT_VOLUME/FL_DISMOUNT call to '/dev/tffsa' */ + { flMountInput in; + + in.type = FL_DISMOUNT; + ioctl_data.inputRecord = ∈ + ioctl_data.outputRecord = &out; + rc = ioctl (fd, FL_IOCTL_MOUNT_VOLUME, &ioctl_data); + if ((rc != 0) || (out.status != flOK)) + fprintf (stderr, "FL_IOCTL_MOUNT_VOLUME/FL_DISMOUNT failed %d\n", out.status); + } + + /* format DiskOnChip */ + { flFlashFormatInput in; + FormatParams3 fp3; + BDTLPartitionFormatParams3 disks[16]; /* WARNING: Large data structure 1 */ + BinaryPartitionFormatParams3 bins[4]; + + memset (&in, 0, sizeof(in)); + memset (&fp3, 0, sizeof(FormatParams3)); + memset (disks, 0, sizeof(disks)); + memset (bins, 0, sizeof(bins)); + + in.fpPtr = &fp3; +#if 1 + in.dwFormatFlags = TL_NORMAL_FORMAT; +#else + /* If you intent on keeping some of BDTL partitions, uncomment + * this section, and specify how many partitions you want to keep. + */ + in.dwFormatFlags = TL_LEAVE_SOME_PARTITIONS; + in.sdwNoOfKeeps = 5; /* keep this many partitions */ +#endif + + fp3.progressCallback = NULL; + fp3.percentUse = 95; + fp3.BDTLPartitionInfo = &disks[0]; + fp3.binaryPartitionInfo = &bins[0]; + fp3.noOfBinaryPartitions = 0; + fp3.noOfBDTLPartitions = 0; + + /* specify size of 1-st DiskOnChip disk */ + disks[ fp3.noOfBDTLPartitions ].length = (40 * 0x100000); /* disk size in bytes */ + disks[ fp3.noOfBDTLPartitions++ ].noOfSpareUnits = 3; +#if 0 + /* specify sizes of 2-nd .. 13-th DiskOnChip disk (if you need them) */ + disks[ fp3.noOfBDTLPartitions ].length = (20 * 0x100000); /* 2-nd disk size in bytes */ + disks[ fp3.noOfBDTLPartitions++ ].noOfSpareUnits = 3; + + disks[ fp3.noOfBDTLPartitions ].length = (30 * 0x100000); /* 3-rd disk size in bytes */ + disks[ fp3.noOfBDTLPartitions++ ].noOfSpareUnits = 3; + + disks[ fp3.noOfBDTLPartitions ].length = (40 * 0x100000); /* 4-th disk size in bytes */ + disks[ fp3.noOfBDTLPartitions++ ].noOfSpareUnits = 3; + + disks[ fp3.noOfBDTLPartitions ].length = (50 * 0x100000); /* 5-th disk size in bytes */ + disks[ fp3.noOfBDTLPartitions++ ].noOfSpareUnits = 3; + + disks[ fp3.noOfBDTLPartitions ].length = (60 * 0x100000); /* 6-th disk size in bytes */ + disks[ fp3.noOfBDTLPartitions++ ].noOfSpareUnits = 3; + + disks[ fp3.noOfBDTLPartitions ].length = (70 * 0x100000); /* 7-th disk size in bytes */ + disks[ fp3.noOfBDTLPartitions++ ].noOfSpareUnits = 3; + + disks[ fp3.noOfBDTLPartitions ].length = (80 * 0x100000); /* 8-th disk size in bytes */ + disks[ fp3.noOfBDTLPartitions++ ].noOfSpareUnits = 3; + + disks[ fp3.noOfBDTLPartitions ].length = (90 * 0x100000); /* 9-th disk size in bytes */ + disks[ fp3.noOfBDTLPartitions++ ].noOfSpareUnits = 3; + + disks[ fp3.noOfBDTLPartitions ].length = (50 * 0x100000); /* 10-th disk size in bytes */ + disks[ fp3.noOfBDTLPartitions++ ].noOfSpareUnits = 3; + + disks[ fp3.noOfBDTLPartitions ].length = (50 * 0x100000); /* 11-th disk size in bytes */ + disks[ fp3.noOfBDTLPartitions++ ].noOfSpareUnits = 3; + + disks[ fp3.noOfBDTLPartitions ].length = (50 * 0x100000); /* 12-th disk size in bytes */ + disks[ fp3.noOfBDTLPartitions++ ].noOfSpareUnits = 3; + + disks[ fp3.noOfBDTLPartitions ].length = (50 * 0x100000); /* 13-th disk size in bytes */ + disks[ fp3.noOfBDTLPartitions++ ].noOfSpareUnits = 3; +#endif + +#if 1 /* specify size of last DiskOnChip disk (if you need it) */ + disks[ fp3.noOfBDTLPartitions ].length = 0; /* take all remaing space on DiskOnChip */ + disks[ fp3.noOfBDTLPartitions++ ].noOfSpareUnits = 3; +#endif + +#if 0 + /* specify size of the first binary partition */ + bins[fp3.noOfBinaryPartitions].length = (1 * 0x100000); /* size in bytes */ + memcpy (bins[fp3.noOfBinaryPartitions].sign, "BIPO", 4); + fp3.noOfBinaryPartitions++; + + /* specify size of the second binary partition */ + bins[fp3.noOfBinaryPartitions].length = (2 * 0x100000); /* size in bytes */ + memcpy (bins[fp3.noOfBinaryPartitions].sign, "BIPO", 4); + fp3.noOfBinaryPartitions++; +#endif + + ioctl_data.inputRecord = ∈ + ioctl_data.outputRecord = &out; + + rc = ioctl (fd, FL_IOCTL_FLASH_FORMAT, &ioctl_data); + + if ((rc != 0) || (out.status != flOK)) + fprintf (stderr, "FL_IOCTL_FLASH_FORMAT failed %d\n", out.status); + } + + /* re-mount disk */ + { flMountInput in; + + in.type = FL_MOUNT; + ioctl_data.inputRecord = ∈ + ioctl_data.outputRecord = &out; + rc = ioctl (fd, FL_IOCTL_MOUNT_VOLUME, &ioctl_data); + if ((rc != 0) || (out.status != flOK)) + fprintf (stderr, "FL_IOCTL_MOUNT_VOLUME/FL_MOUNT failed %d\n", out.status); + } + + /* WARNING: You must kill DiskOnChip driver and reboot your system now ! */ + return rc; +} + +#endif /* ALLOW_FORMATTING */ + + + + +#ifdef ALLOW_FORMATTING + +static +int fl_ioctl_flash_unformat (int fd) +{ + flIOctlRecord ioctl_data; + flOutputStatusRecord out; + int rc; + + /* unmount disk before formatting */ + { flMountInput in; + + in.type = FL_DISMOUNT; + ioctl_data.inputRecord = ∈ + ioctl_data.outputRecord = &out; + rc = ioctl (fd, FL_IOCTL_MOUNT_VOLUME, &ioctl_data); + if ((rc != 0) || (out.status != flOK)) + fprintf (stderr, "FL_IOCTL_MOUNT_VOLUME/FL_DISMOUNT failed %d\n", out.status); + } + + { flFlashUnformatInput in; + + in.dwFlags = 0; + ioctl_data.inputRecord = ∈ + ioctl_data.outputRecord = &out; + rc = ioctl (fd, FL_IOCTL_FLASH_UNFORMAT, &ioctl_data); + if ((rc != 0) || (out.status != flOK)) + fprintf (stderr, "FL_IOCTL_FLASH_UNFORMAT failed %d\n", out.status); + } + + /* WARNING: You must kill DiskOnChip driver and reboot your system now ! */ + return rc; +} + +#endif /* ALLOW_FORMATTING */ + + + + +static +int hdio_getgeo (int fd) +{ + struct hd_geometry + { + unsigned char heads; + unsigned char sectors; + unsigned short cylinders; + unsigned long start; + }; + + struct hd_geometry geo; + int rc; + + if ((rc = ioctl(fd, 0x0301 /* HDIO_GETGEO */, &geo)) != 0) + perror ("Error in HDIO_GETGEO"); + else + printf ("Disk geometry: %d heads, %d cylinders, %d sectors, start sector %ld\n", + (int)geo.heads, (int)geo.cylinders, (int)geo.sectors, geo.start); + return rc; +} + + + +#ifdef ALLOW_BDK + +static +int fl_ioctl_bdk_operation (int fd) +{ + flIOctlRecord ioctl_data; + int buf_size = (4 * 1024); + char * buf; + char * buf2; + int rc; + register int iBin = 0; + + /* allocate buffers */ + if ((buf = malloc(buf_size)) == NULL) + { + fprintf (stderr, "Can't alloc buffer"); + return -1; + } + if ((buf2 = malloc(buf_size)) == NULL) + { + fprintf (stderr, "Can't alloc buffer"); + free (buf); + return -1; + } + +#if 0 + for (; iBin <= 1; iBin++) +#endif + { + /* set this binary partition as the target of subsequent IOCTLs */ + + { flInputLnxRecord in; + flOutputLnxRecord out; + + in.command = 0; + in.data = mk_tffs_handle (0, 0); + + ioctl_data.inputRecord = ∈ + ioctl_data.outputRecord = &out; + + rc = ioctl (fd, FL_IOCTL_LNX, &ioctl_data); + if ((rc != 0) || (out.status != flOK)) + { + fprintf (stderr, "FL_IOCTL_LNX failed %d\n", (int)out.status); + rc = -1; + goto quit; + } + } + + /* write, the read back and verify 'buf_size' bytes to this binary partition */ + + { flBDKOperationInput in; + flOutputStatusRecord out; + + fprintf (stdout, "Writing %d bytes to binary partition %d\n", buf_size, iBin); + + in.type = BDK_GET_INFO; + in.bdkStruct.flags = 0; + in.bdkStruct.length = 0; + in.bdkStruct.startingBlock = 0; + in.bdkStruct.bdkBuffer = NULL; + in.bdkStruct.signOffset = 8; + if (iBin == 0) + memcpy (in.bdkStruct.oldSign, "BIPO", 4); + else + memcpy (in.bdkStruct.oldSign, "BIPO", 4); + ioctl_data.inputRecord = ∈ + ioctl_data.outputRecord = &out; + rc = ioctl (fd, FL_IOCTL_BDK_OPERATION, &ioctl_data); + if ((rc != 0) || (out.status != flOK)) + { + fprintf (stderr, "FL_IOCTL_BDK_OPERATION/BDK_GET_INFO failed %d\n", out.status); + rc = -1; + goto quit; + } + + in.type = BDK_INIT_WRITE; + in.bdkStruct.flags = 0; + in.bdkStruct.length = buf_size; + in.bdkStruct.bdkBuffer = NULL; + in.bdkStruct.signOffset = 8; + if (iBin == 0) + { + in.bdkStruct.startingBlock = 0; + memcpy (in.bdkStruct.oldSign, "BIPO", 4); + } + else + { + in.bdkStruct.startingBlock = 15; + memcpy (in.bdkStruct.oldSign, "BIPO", 4); + } + ioctl_data.inputRecord = ∈ + ioctl_data.outputRecord = &out; + rc = ioctl (fd, FL_IOCTL_BDK_OPERATION, &ioctl_data); + if ((rc != 0) || (out.status != flOK)) + { + fprintf (stderr, "FL_IOCTL_BDK_OPERATION/BDK_INIT_WRITE failed %d\n", out.status); + rc = -1; + goto quit; + } + + in.type = BDK_WRITE; + in.bdkStruct.flags = ERASE_BEFORE_WRITE; + in.bdkStruct.length = buf_size; + in.bdkStruct.bdkBuffer = buf; + memset (buf, '$', buf_size); + ioctl_data.inputRecord = ∈ + ioctl_data.outputRecord = &out; + rc = ioctl (fd, FL_IOCTL_BDK_OPERATION, &ioctl_data); + if ((rc != 0) || (out.status != flOK)) + { + fprintf (stderr, "FL_IOCTL_BDK_OPERATION/BDK_WRITE failed %d\n", out.status); + rc = -1; + goto quit; + } + + fprintf (stdout, "SUCCESS writing %d bytes to binary partition %d\n", buf_size, iBin); + + fprintf (stdout, "Reading back and verifying %d bytes from binary partition %d\n", buf_size, iBin); + + in.type = BDK_INIT_READ; + ioctl_data.inputRecord = ∈ + ioctl_data.outputRecord = &out; + rc = ioctl (fd, FL_IOCTL_BDK_OPERATION, &ioctl_data); + if ((rc != 0) || (out.status != flOK)) + { + fprintf (stderr, "FL_IOCTL_BDK_OPERATION/BDK_INIT_READ failed %d\n", out.status); + rc = -1; + goto quit; + } + + in.type = BDK_READ; + in.bdkStruct.bdkBuffer = buf2; + memset (buf2, 0, buf_size); + ioctl_data.inputRecord = ∈ + ioctl_data.outputRecord = &out; + rc = ioctl (fd, FL_IOCTL_BDK_OPERATION, &ioctl_data); + if ((rc != 0) || (out.status != flOK)) + { + fprintf (stderr, "FL_IOCTL_BDK_OPERATION/BDK_READ failed %d\n", out.status); + rc = -1; + goto quit; + } + + if( memcmp(buf, buf2, buf_size) != 0) + { + fprintf (stderr, "Error: mismatching data\n"); + rc = -1; + goto quit; + } + fprintf (stdout, "SUCCESS reading back and verifying data\n"); + } + } /* for(iBin) */ + +quit: + + free (buf); + free (buf2); + + return rc; +} + +#endif /* ALLOW_BDK */ + + + +#ifdef ALLOW_HW_PROTECTION + +/* + * This routine sets TrueFFS handle for subsequent IOCTLs + */ +static +int set_ioctl_handle (int fd, int tffs_handle) +{ + flIOctlRecord ioctl_data; + flInputLnxRecord in; + flOutputLnxRecord out; + int rc; + + ioctl_data.inputRecord = ∈ + ioctl_data.outputRecord = &out; + + in.command = 0; + in.data = tffs_handle; + + rc = ioctl (fd, FL_IOCTL_LNX, &ioctl_data); + if ((rc != 0) || (out.status != flOK)) + { + fprintf (stderr, "FL_IOCTL_LNX failed %d\n", (int)out.status); + rc = -1; + } + else + fprintf (stdout, "SUCCESS setting handle 0x%x for future IOCTLs\n", tffs_handle); + + return rc; +} + + + +/* + * This routine provides example of using FL_IOCTL_..._HW_PROTECTION + * IOCTLs to insert key into protected partition. + */ +static +int fl_ioctl_hw_protection (int fd, int ioctl_opcode) +{ + flIOctlRecord ioctl_data; + int socket_no = 0; + int partition_no; + int rc; + + partition_no = /* specify your own partition here */ 0; + + /* set TrueFFS handle for subsequent IOCTL */ + + rc = set_ioctl_handle (fd, mk_tffs_handle(socket_no, partition_no)); + if (rc != 0) + return rc; + + /* insert key into partition */ + + { flProtectionInput in; + flProtectionOutput out; + + ioctl_data.inputRecord = ∈ + ioctl_data.outputRecord = &out; + + in.type = PROTECTION_INSERT_KEY; + + /* this is my usual key; replace it with your own */ + + in.key[0] = 'p'; + in.key[1] = 'i'; + in.key[2] = 's'; + in.key[3] = 's'; + in.key[4] = 'w'; + in.key[5] = 'o'; + in.key[6] = 'r'; + in.key[7] = 'd'; + + in.protectionType = 0; /* not actually used by PROTECTION_INSERT_KEY */ + + rc = ioctl (fd, ioctl_opcode, &ioctl_data); + if ((rc != 0) || (out.status != flOK)) + fprintf (stderr, "%d IOCTL failed %d\n", ioctl_opcode, out.status); + else + fprintf (stdout, "SUCCESS inserting protection key\n"); + } + + /* for security, set TrueFFS handle to impossible value (0xffff) */ + + set_ioctl_handle (fd, 0xffff); + + return rc; +} + +#endif /* ALLOW_HW_PROTECTION */ + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/ioctl_example/Makefile linux-2.6.30.4/drivers/block/tffs/ioctl_example/Makefile --- linux-2.6.30.4-orig/drivers/block/tffs/ioctl_example/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/ioctl_example/Makefile 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,72 @@ +#=============================================================================== +# +# Makefile for IOCTL demo application for DOC driver. +# +#=============================================================================== +# +# Copyright (C) 2006 msystems Ltd. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of msystems nor the names of its contributors may be +# used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +#=============================================================================== + + +# +# Specify root directory of Linux kernel's source tree as appropriate +# for your installation. +# +KERNEL_DIR = /opt/ti/omap2420/kernel/269 + +# +# Specify which compiler to use (default is ARM/GCC compiler) +# +CC = arm-unknown-linux-gnu-gcc + +# +# Specify compiler flags in the same fashion as 'make modules' does. +# Flags below are appropriate for XScale compilation. +# +CFLAGS += -I$(KERNEL_DIR)/include +CFLAGS += -I.. +CFLAGS += -Wall +# CFLAGS += -g + +# +# 'make all' rule +# +all : ioctl-example + +# +# make 'ioctl-example' demo application +# +ioctl-example : ioctl-example.c + $(CC) $(CFLAGS) -o $@ $< + +# +# 'make clean' rule +# +clean : + rm -f *.o ioctl-example + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/LICENSE.TXT linux-2.6.30.4/drivers/block/tffs/LICENSE.TXT --- linux-2.6.30.4-orig/drivers/block/tffs/LICENSE.TXT 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/LICENSE.TXT 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,412 @@ +Disclaimer of Liability +----------------------- + +SanDisk IL Ltd.'s general policy does not recommend the use of its products +in life support applications wherein a failure or malfunction of the +product may directly threaten life or injury. +Accordingly, in any use of products in life support systems or other +applications where failure could cause damage, injury or loss of life, +the products should only be incorporated in systems designed with +appropriate redundancy, fault tolerant or back-up features. + +SanDisk IL shall not be liable for any loss, injury or damage caused by +use of the Products in any of the following applications: + +Special applications such as military related equipment, nuclear reactor +control, and aerospace + +Control devices for automotive vehicles, train, ship and traffic +equipment + +Safety system for disaster prevention and crime prevention + +Medical-related equipment including medical measurement device. + + +Contact Information +------------------- + +For comments, questions and bug reports, please contact your SanDisk +representative or email us at oemsupport@sandisk.com. + +This document is for information use only and is subject to change without +prior notice. + +SanDisk IL Ltd. assumes no responsibility for any errors that may appear +in this document, nor for incidental or consequential damages resulting +from the furnishing, performance or use of this material. + +SanDisk IL's products are not warranted to operate without failure. +SanDisk IL's general policy does not recommend the use of its products +in life support applications where a failure or malfunction of the product +could cause injury or loss of life. Per SanDisk IL's Terms and Conditions +of Sale,the user of SanDisk IL's products in life support applications +assumes all risk of such use and indemnifies SanDisk IL against all damages. +See "Disclaimer of Liability". Accordingly, in any use of the Product in +life support systems or other applications where failure could cause injury +or loss of life, the Product should only be incorporated in systems designed +with appropriate and sufficient redundancy or backup features. + +All parts of the SanDisk IL's documentation are protected by copyright law +and all rights reserved. + +Contact your local SanDisk sales office or distributor to obtain the latest +specifications before placing your order. + +(C) 1995-2007 SanDisk IL Ltd. All rights reserved. + +mDOC, DOC, TrueFFS, SureFS, SanDisk and SanDisk logo are registered +trademarks of SanDisk IL Ltd. and SanDisk Corporation, respectively. +Other product names or service marks mentioned herein may be trademarks +or registered trademarks of their respective owners. + + +DOC Driver for Linux 2.6, Version 1.0—Block device driver for mDOC H3 +family of devices under Linux kernel 2.6—is licensed pursuant to the +GNU General Public License, Version 2, copied below. + +Email questions: oemsupport@sandisk.com +© SanDisk IL Ltd. 1995-2007 +SanDisk IL Ltd., 7 Atir Yeda Street, Kfar Saba 44425, Israel + + +GNU GENERAL PUBLIC LICENSE +Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/Makefile linux-2.6.30.4/drivers/block/tffs/Makefile --- linux-2.6.30.4-orig/drivers/block/tffs/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/Makefile 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,31 @@ +# +# DOC driver Makefile for Linux 2.6. +# Copyright (C) 2006, msystems Ltd. All rights reserved. +# +# Use this Makefile if you want to link DOC driver statically +# with the Linux kernel. +# + +obj-y += tffs.o + +tffs-objs := trace32.o +tffs-objs += defs.o +tffs-objs += docdrv.o +tffs-objs += doch_api.o +tffs-objs += doch_ata.o +tffs-objs += dochstub.o +tffs-objs += dochtl.o +tffs-objs += docsys.o +tffs-objs += extfiltr.o +tffs-objs += fatfilt.o +tffs-objs += flbase.o +tffs-objs += flcustom.o +tffs-objs += flioctl.o +tffs-objs += flsystem.o +tffs-objs += hal_nor.o +tffs-objs += tffs2lnx.o +tffs-objs += tffs_api.o +tffs-objs += tffsarch.o +tffs-objs += tffs-pm26.o +tffs-objs += tffsdrv26.o + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/Makefile-m linux-2.6.30.4/drivers/block/tffs/Makefile-m --- linux-2.6.30.4-orig/drivers/block/tffs/Makefile-m 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/Makefile-m 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,31 @@ +# +# DOC driver Makefile for Linux 2.6. +# Copyright (C) 2006, msystems Ltd. All rights reserved. +# +# Use this Makefile if you want to build DOC driver as loadable +# kernel module. +# + +obj-m += tffs.o + +tffs-objs := trace32.o +tffs-objs += defs.o +tffs-objs += docdrv.o +tffs-objs += doch_api.o +tffs-objs += doch_ata.o +tffs-objs += dochstub.o +tffs-objs += dochtl.o +tffs-objs += docsys.o +tffs-objs += extfiltr.o +tffs-objs += fatfilt.o +tffs-objs += flbase.o +tffs-objs += flcustom.o +tffs-objs += flioctl.o +tffs-objs += flsystem.o +tffs-objs += hal_nor.o +tffs-objs += tffs2lnx.o +tffs-objs += tffs_api.o +tffs-objs += tffsarch.o +tffs-objs += tffs-pm26.o +tffs-objs += tffsdrv26.o + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/Makefile-omap2420 linux-2.6.30.4/drivers/block/tffs/Makefile-omap2420 --- linux-2.6.30.4-orig/drivers/block/tffs/Makefile-omap2420 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/Makefile-omap2420 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,137 @@ +############################################################################### +# +# DOC driver Makefile for Linux 2.6. +# Copyright (C) 2006, msystems Ltd. All rights reserved. +# +# Use this Makefile if you want to build DOC driver outside of Linux +# kernel's source code tree. You will need to change the following +# macros in this Makefile as appropriate for your project: +# KERNEL_DIR +# CC +# CFLAGS +# LD +# LDFLAGS +# +############################################################################### + +# +# Specify name of this kernel module +# +MODULE_NAME = tffs + +# +# Specify root directory of kernel's source tree as appropriate +# for your installation. +# +KERNEL_DIR = /opt/ti/omap2420/kernel/269 + +# +# Specify which compiler to use (default is ARM/GCC compiler) +# +CC = arm-unknown-linux-gnu-gcc + +# +# Specify compiler flags in the same fashion as 'make modules' does. +# Flags below are appropriate for ARM compilation. +# +CFLAGS += -nostdinc +CFLAGS += -iwithprefix include +CFLAGS += -D__KERNEL__ +CFLAGS += -I$(KERNEL_DIR)/include +CFLAGS += -Wall +CFLAGS += -Wstrict-prototypes +CFLAGS += -Wno-trigraphs +CFLAGS += -fno-strict-aliasing +CFLAGS += -fno-common + +# Uncomment line below if you want compiler to optimize for speed +# CFLAGS += -O2 +# Uncomment line below if you want compiler to optimize for space +# CFLAGS += -Os +# Uncomment line below if you are going to debug DOC driver +# CFLAGS += -g + +CFLAGS += -Wdeclaration-after-statement +CFLAGS += -fno-omit-frame-pointer +CFLAGS += -mapcs +CFLAGS += -mno-sched-prolog +CFLAGS += -mlittle-endian +CFLAGS += -mapcs-32 +CFLAGS += -D__LINUX_ARM_ARCH__=6 +CFLAGS += -march=armv5t +CFLAGS += -Wa,-march=armv6 +CFLAGS += -mtune=strongarm +CFLAGS += -malignment-traps +CFLAGS += -msoft-float +CFLAGS += -Uarm +CFLAGS += -DMODULE +CFLAGS += -DKBUILD_BASENAME=$(MODULE_NAME) +CFLAGS += -DKBUILD_MODNAME=$(MODULE_NAME) +# CFLAGS += -DTRACE32 +CFLAGS += -c + +# +# Uncomment line below only if you are using multiple cascaded +# mDOC devices +# +# CFLAGS += -DATA_MAX_NUM_OF_DEVICES=2 +# + +# +# Specify which linker to use (default is ARM linker) +# +LD = arm-unknown-linux-gnu-ld + +# +# Specify linker flags in the same fashion as 'make modules' does. +# Flags below are appropriate for ARM compilation. +# +LDFLAGS = -EL +LDFLAGS += -r + +# +# Module's objects: +# - trace32.o (if used) must be first in the link order ! +# - $(MODULE_NAME).mod.o must be last in the link order ! +# +OBJS = trace32.o +OBJS += defs.o +OBJS += docdrv.o +OBJS += doch_api.o +OBJS += doch_ata.o +OBJS += dochstub.o +OBJS += dochtl.o +OBJS += docsys.o +OBJS += extfiltr.o +OBJS += fatfilt.o +OBJS += flbase.o +OBJS += flcustom.o +OBJS += flioctl.o +OBJS += flsystem.o +OBJS += hal_nor.o +OBJS += tffs2lnx.o +OBJS += tffs_api.o +OBJS += tffsarch.o +OBJS += tffs-pm26.o +OBJS += tffsdrv26.o +OBJS += $(MODULE_NAME).mod.o + +# +# rule for building loadable kernel module +# +$(MODULE_NAME).ko : $(OBJS) + $(LD) $(LDFLAGS) -o $@ $(OBJS) + +# +# C compilation rules +# +%.o: %.c + $(CC) $(CFLAGS) -o $@ $< + +# +# 'make clean' rule +# +clean : + rm *.o *.ko + + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/Makefile-pxa27x linux-2.6.30.4/drivers/block/tffs/Makefile-pxa27x --- linux-2.6.30.4-orig/drivers/block/tffs/Makefile-pxa27x 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/Makefile-pxa27x 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,177 @@ +#============================================================== +# +# Makefile for building DiskOnChip driver loadable module +# for Linux 2.6.x kernels +# +# Version 1.0 +# +#============================================================== + + +# +# Specify name of this kernel module +# +MODULE_NAME = tffs + + +# +# Specify root directory of Linux kernel's source tree as appropriate +# for your installation. +# +KERNEL_DIR = /opt/mobilinux41/pxa27x/andrayk/kernel/2.6.10 + + +# +# Specify which compiler to use (default is XScale compiler) +# +CC = iwmmxt_le-gcc + + +# +# Specify compiler flags in the same fashion as 'make modules' does. +# Flags below are appropriate for XScale compilation. +# +CFLAGS += -nostdinc +CFLAGS += -iwithprefix include +CFLAGS += -D__KERNEL__ +CFLAGS += -I$(KERNEL_DIR)/include +CFLAGS += -Wall +CFLAGS += -Wstrict-prototypes +CFLAGS += -Wno-trigraphs +CFLAGS += -fno-strict-aliasing +CFLAGS += -fno-common +# CFLAGS += -Os +CFLAGS += -fno-omit-frame-pointer +CFLAGS += -g +CFLAGS += -marm +CFLAGS += -fno-omit-frame-pointer +CFLAGS += -mapcs +CFLAGS += -mno-sched-prolog +CFLAGS += -mlittle-endian +CFLAGS += -mabi=aapcs +CFLAGS += -mno-thumb-interwork +CFLAGS += -D__LINUX_ARM_ARCH__=5 +CFLAGS += -march=armv5te +CFLAGS += -mtune=xscale +CFLAGS += -Wa,-mcpu=xscale +CFLAGS += -msoft-float +CFLAGS += -Uarm +CFLAGS += -Wdeclaration-after-statement +CFLAGS += -DMODULE +CFLAGS += -DKBUILD_BASENAME=$(MODULE_NAME) +CFLAGS += -DKBUILD_MODNAME=$(MODULE_NAME) +# CFLAGS += -DTRACE32 +CFLAGS += -c + +# +# Uncomment line below only if you are using multiple cascaded +# mDOC devices +# +# CFLAGS += -DATA_MAX_NUM_OF_DEVICES=2 +# + +# +# Specify which linker to use (default is XScale linker) +# +LD = iwmmxt_le-ld + + +# +# Specify linker flags in the same fashion as 'make modules' does. +# Flags below are appropriate for XScale compilation. +# +LDFLAGS = -EL +LDFLAGS += -r + + +# +# Module's headers +# +H_FILES = flcustom.h +H_FILES += flsystem.h +H_FILES += extfiltr.h +H_FILES += tffs2lnx.h +H_FILES += tffsarch.h +H_FILES += tffsdrv.h +H_FILES += _tffsioct.h +H_FILES += tffsioct.h +H_FILES += bddefs.h +H_FILES += blockdev.h +H_FILES += _common.h +H_FILES += defs.h +H_FILES += docbdk.h +H_FILES += _docsys.h +H_FILES += docsys.h +H_FILES += dosformt.h +H_FILES += fatfilt.h +H_FILES += flbase.h +H_FILES += flbuffer.h +H_FILES += flchkdef.h +H_FILES += flcommon.h +H_FILES += flioctl.h +H_FILES += flstdcmp.h +H_FILES += flstruct.h +H_FILES += flsysfun.h +H_FILES += flsystyp.h +H_FILES += _fltl.h +H_FILES += fltl.h +H_FILES += part_inf.h +H_FILES += bdkemul.h +H_FILES += _dochapi.h +H_FILES += doch_api.h +H_FILES += doch_ata.h +H_FILES += doch_func.h +H_FILES += doch_sys.h +H_FILES += dochstub.h +H_FILES += dochtl.h +H_FILES += hal_nor.h +H_FILES += hib.h +H_FILES += tffs_api.h + +# +# Module's objects: +# - trace32.o (if used) must be first in the link order ! +# - $(MODULE_NAME).mod.o must be last in the link order ! +# +OBJS = trace32.o +OBJS += defs.o +OBJS += docdrv.o +OBJS += doch_api.o +OBJS += doch_ata.o +OBJS += dochstub.o +OBJS += dochtl.o +OBJS += docsys.o +OBJS += extfiltr.o +OBJS += fatfilt.o +OBJS += flbase.o +OBJS += flcustom.o +OBJS += flioctl.o +OBJS += flsystem.o +OBJS += hal_nor.o +OBJS += tffs2lnx.o +OBJS += tffs_api.o +OBJS += tffsarch.o +OBJS += tffs-pm26.o +OBJS += tffsdrv26.o +OBJS += $(MODULE_NAME).mod.o + + +# +# rule for building loadable kernel module +# +$(MODULE_NAME).ko : $(OBJS) + $(LD) $(LDFLAGS) -o $@ $(OBJS) + +# +# C compilation rules +# +%.o: %.c + $(CC) $(CFLAGS) -o $@ $< + +# +# 'make clean' rule +# +clean : + rm *.o *.ko + +################ Thank you for using M-Systems' products. #################### diff -urN linux-2.6.30.4-orig/drivers/block/tffs/part_inf.h linux-2.6.30.4/drivers/block/tffs/part_inf.h --- linux-2.6.30.4-orig/drivers/block/tffs/part_inf.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/part_inf.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,227 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ + +/***********************************************************************************/ +/* */ +/* This file contains various structure and defines concerning Partition info and */ +/* access */ +/* */ +/***********************************************************************************/ + +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Test for 7.x/src/H3/part_inf.h-arc $ + * + * Rev 1.20 Oct 22 2007 11:34:54 einat.avidan + * update copyrights header + * + * Rev 1.19 Feb 28 2007 09:53:48 einat.avidan + * No change + * + * Rev 1.18.1.0 Nov 30 2006 10:24:10 Yaniv.Iarovici + * Added 'DOCH_SecureDeleteDev1' to SDK Device Attributes. + * + * Rev 1.18 Sep 11 2006 13:45:26 yaniv.iarovici + * Legal header added + * + * Rev 1.17 Aug 09 2006 17:26:58 Polina.Marimont + * initial for DOC Driver 1.0 + * + * Rev 1.16.1.0 Aug 08 2006 15:55:32 Polina.Marimont + * DOC Driver 1.0 initial + * + * Rev 1.16 May 28 2006 13:02:34 polina.marimont + * 1. IDENTIFY DEVICE interface update + * 2. floors fix for format, where partition ended at the end of floor 0 + * + * Rev 1.15 May 18 2006 14:41:24 polina.marimont + * v1.40Fin1, PVCS log inside + */ + +#ifndef _PARTITION_INFO_H +#define _PARTITION_INFO_H + +#include "doch_api.h" + +/* Extended device info structure*/ +typedef struct { + FLWord wFlashType; + FLWord wPhysicalPageSize; /*In Sectors*/ + FLWord wNumOfPhysicalPagesInPhysicalErasableBlockSize; + FLWord wNumOfErasableBlocksPerPhysicalChip; + FLWord wPhysicalChipBusWidth; /*8/16*/ + FLWord wNumOfChipsOnDataBus; /*1..2*/ + FLWord wFlashChipNumOfPlanes; /*1..4*/ + FLWord wFlashChipNumOfBanks; /*Independently accessible parts of flash array*/ + FLWord wLogicalPageSize; /*In Sectors*/ + FLWord wNumOfLogicalPagesInLogicalErasableBlockSize; + FLWord wTotalNumOfLogicalErasableUnits; + FLWord wMapinfoUnitsUsed; + FLWord wLUNCurrentlyUsed; + FLWord wFreeUnitsOnMedia; + FLByte bReserved1[0x1E4]; +} DOCH_ExtendedDeviceInfo; + +/*Partition user attributes +512Byte overall (1 sector) +First DOCH_PART_INFO_SDK_RESERVED_BYTES bytes are reserved for SDK*/ +#define DOCH_PART_INFO_SDK_RESERVED_BYTES 0x40 +typedef struct { + FLByte bReserved1[DOCH_PART_INFO_SDK_RESERVED_BYTES]; /*For SDK use*/ + FLByte bReserved2[DOCH_SECTOR_SIZE - DOCH_PART_INFO_SDK_RESERVED_BYTES]; /*For application use*/ +} DOCH_PartitionUserAttr; + +/*Device user attributes +512Byte overall (1 sector) +First DOCH_DEVICE_INFO_SDK_RESERVED_BYTES bytes are reserved for SDK*/ +#define DOCH_DEVICE_INFO_SDK_RESERVED_BYTES 0x40 + +typedef struct { + FLByte bLastDev0PartSpanned; + FLByte numOfSpannedPartitionOnDev0; + FLByte secondFloorActive; /*At least 1 user partition resides on Dev1*/ + FLByte bLastPartitionOnDev0; /*Number of last partition that resides on Dev0*/ + FLDword dwSpanSector; /*Which sector in the spanned partition is the last that resides on dev0*/ + FLDword dwSpanSizeOnDev0; /*How many sectors on Dev0*/ + FLByte spare[4]; +} DOCH_PartitionSpanData; + +typedef struct { + FLDword dwSecureDeleteStartSector; + FLDword dwSecureDeleteNumOfSectors; + FLByte bOperationRequired; + FLByte bPart; + FLByte spare[2]; +} DOCH_SecureDeleteDev1; + +typedef struct { + DOCH_PartitionSpanData sSpanInfo; + DOCH_SecureDeleteDev1 sSecureDeleteDev1; + FLByte spare[0x24]; /*Rest of 0x40 bytes that are reserved for SDK use*/ +} DOCH_SDKDeviceAttr; + +typedef struct { + DOCH_SDKDeviceAttr sdkAttributes; + FLByte bReserved2[DOCH_SECTOR_SIZE - DOCH_DEVICE_INFO_SDK_RESERVED_BYTES]; /*For application use*/ +} DOCH_DeviceUserAttr; + + +/******************************************************************************/ +/* + * Configuration Partition structure, sub-structures and ENUMS + */ +/******************************************************************************/ + +/*Configuration Partition Layout*/ + +/*Sector #0*/ +typedef struct { + FLWord wVersion; + FLWord wCompatabilityVersion; + FLDword dwCommandFlagsOrStatuses; + FLDword dwDiskAttributes1; + FLDword dwGateKeeperAttr; /*FLDword dwDiskAttributes2;*/ + FLByte bReserved2[0x10]; + FLByte bUniqueID[0x10]; + FLByte bReserved3[0x10]; + FLByte bSerialNumber[0x14]; + FLByte bModelNumber[0x28]; + FLByte breserved4[2]; + FLWord wDefaultPartitionNumber; + FLDword dwUnformattedCapacity; /*In Sectors*/ + FLDword dwConfigurationPartitionExistsSign; + FLDword dwETFFSVER; + FLDword dwConfigPartitionSize; /*In Bytes*/ + FLByte bProgrammerName[0x10]; + FLByte bProgrammerVersion[0x8]; + FLByte bReserved6[0x58]; + FLByte bGateKeeperKey[0x80]; + FLByte bGateKeeperKeyReservedLargerKey[0x80]; +} DOCH_ConfigPartitionSector0; + +/*Sector #1*/ +typedef enum { + DOCH_MP_AUTH_TYPE_NONE = 0, /*No master password*/ + DOCH_MP_AUTH_TYPE_PWD = 1, /*Password protection (Null terminated)*/ + DOCH_MP_AUTH_TYPE_RSA = 2 /*RSA Protection (All 128Bytes are significant*/ +} DOCH_MasterPwdAuthType; + +typedef enum { + DOCH_MAO_MASTER_PWD_AUTH_TYPE = 0 +} DOCH_MasterAttributes_Offset; + +typedef enum { + DOCH_MAB_MASTER_PWD_AUTH_TYPE = 0x0000003F +} DOCH_MasterAttributes_Bits; + +typedef struct { + FLByte bReserved1[0xC]; + FLDword masterAttributes; + FLByte bReserved2[0xF0]; + FLByte bMasterPasskey[0x80]; + FLByte bReservedLargeMasterPasskey[0x80]; +} DOCH_ConfigPartitionSector1; + +/*Sector #2*/ +typedef struct { + FLByte bDochPublicKey[0x80]; + FLByte bReserved1[0x80]; + FLByte bDochPrivateKey[0x80]; + FLByte bReserved2[0x80]; +} DOCH_ConfigPartitionSector2; + +/*Sector #3*/ +/*Identical to DOCH_DriveParameters structure (ATA IDENTIFY_DEVICE structure)*/ + +/*Sectors #4..#14 are reserved*/ + +/*Sector #15 - OTP sector for tester*/ +typedef struct { + FLByte bUniqueID[0x10]; + FLByte bReserved1[0x10]; + FLByte bSerialNumber[0x14]; + FLByte bModelNumber[0x28]; + FLByte bReserved2[0x1A4]; +} DOCH_ConfigPartitionSector15; + + +#endif /*_PARTITION_INFO_H*/ diff -urN linux-2.6.30.4-orig/drivers/block/tffs/README.TXT linux-2.6.30.4/drivers/block/tffs/README.TXT --- linux-2.6.30.4-orig/drivers/block/tffs/README.TXT 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/README.TXT 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,1094 @@ + + ******************************************************************************* + * * + * DOC Driver for Linux 2.6 * + * Source Code Edition * + * * + * * + * INSTALLATION MANUAL * + * * + * * + * Version 1.0.85-RTM, released on April 27 2008 * + * Based on DOC Driver Block Device SDK version 1.1.0 RTM * + * * + * Email questions to: oemsupport@sandisk.com * + * Copyright (C) SanDisk IL Ltd. 1995 - 2008 * + * SanDisk IL Ltd., 7 Atir Yeda Street, Kfar Saba 44425, Israel * + * * + * Please note that effective January 1, 2007, the name msystems Ltd. was * + * changed to SanDisk IL Ltd. * + * * + ******************************************************************************* + * * + * 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 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, which is set forth in the readme.txt file. * + * 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., 51 * + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + * * + * This License does not grant you any right to use the trademarks, service * + * marks or logos of SanDisk IL Ltd. or SanDisk Corporation. * + * Subject to the foregoing, SanDisk IL Ltd., for itself and on behalf of its * + * licensors, hereby reserves all intellectual property rights in the program, * + * except for the rights expressly granted in this License. * + * * + ******************************************************************************* + + + Contents + ======== + + 1. Introduction + 2. Supported types of mDOC devices + 3. Conventions used in this document + 4. DOC driver's general configuration options + 5. Board specific configuration options + 6. Configuring DOC driver to use Direct Memory Access (DMA) + 7. Configuring DOC driver to use mDOC READY interrupt + 8. Compiling DOC driver + 9. Installing DOC driver + 10. Using DOC driver + 11. Configuring DOC driver to reduce power consumption + 12. Improving DOC driver's I/O performance + 13. Reducing DOC driver's load on CPU + 14. Access to DOC driver's Extended Functions + 15. Formatting mDOC + 16. Updating firmware in mDOC devices + 17. Memory footprint + 18. Known limitations + 19. Disclaimer of Liability + 20. Contact information + + + 1. Introduction + =============== + + 1.1. This document explains how to install DOC driver, and use mDOC device + with Linux operating system. The information in this document applies + to 2.6.x versions of the Linux kernel. + + 1.2. The mDOC devices are high performance, low cost data storage products + based on the latest flash technology. The mDOC devices serve two + purposes under Linux: + + (1) Main data storage device + + In this role, mDOC devices serve the same purpose that + conventional hard disks serve in Linux servers or workstations - + they store various Linux kernel componenets (such as device + drivers, Linux libraries and configuration files), user + applications etc. + + (2) System's boot device + + All mDOC devices feature ROM area which can be programmed via + IOCTL calls to DOC driver. Boards developers usually arrange + for this ROM area to appear at CPU's reset vector, and software + developers program board-specific bootstrap code into it. When + CPU is reset, it executes this bootstrap code, and boots Linux + system entirely from mDOC device. Dedicated boot devices such as + separate ROM or NOR flash chips are no longer needed. + + This document describes only the data storage function of mDOC devices. + + 1.3. Although mDOC devices use multi-level cell NAND flash technology + internally, DOC driver completely hides this fact from the user, and + implements traditional block device interface. This allow mDOC devices + to works with all standard disk-oriented Linux file systems (such as + EXT2, EXT3 etc.). In that respect DOC driver is similar to ATA hard + disks and CompactFlash cards, and is different from other NAND or NOR + flash devices (which must be managed by flash-specific file systems such + as JFFS2). All standard disk oriented Linux utilities (such as 'fdisk', + 'du' etc.) work with mDOC devices. + + 1.4. DOC driver is distributed in the source code form, and is expected to + be compiled at customer's site. Instructions on how to configure and + compile DOC driver are provided in later chapters in this document. + + + + 2. Supported types of mDOC devices + ================================== + + 2.1. This version of DOC driver supports the following types of mDOC + devices: + + - mDOC H3 family + + ===> NOTE. This version of DOC driver will NOT work with the + following types of mDOC devices: + + G3/P3 family + G4 family + H1 family + + You will need to use TrueFFS driver version 7.1.0 (or higher) + with these types of mDOC devices. + + + + 3. Conventions used in this document + ==================================== + + 3.1. Term "host" is used in this document to refer to computer where DOC + driver's source code is located, and where DOC driver is compiled and + linked. Typically "hosts" are engineering workstations running RedHat + or SUSE Linux, or Windows operating systems. + + Term "target" is used in this document to refer to computer where DOC + driver's executable runs, and where mDOC devices are installed. Typical + targets are mobile devices powered by ARM or XScale microprocessors, + specialized communication equipment powered by PowerPC microprocessors, + and various other embedded systems. + + ===> NOTE. Although usually host and target are different systems, in + some cases "host" and "target" could actually refer to the + same system. For example, it is possible to plug mDOC into + the PCI slot of PC workstation running Linux. If this + workstation contains kernel's source tree installed on it, + then it is possible to compile DOC driver, and run it on + this workstation. In this case PC workstation serves both + as host and target system. + + All instructions provided by this document refer to the case when + "host" and "target" are separate systems. + + 3.2. Installation instructions in this document assume that user is logged + into the system as "root". + + + + 4. DOC driver's general configuration options + ============================================= + + 4.1. Linux kernel requires that every device driver use unique major device + number. By default, DOC driver uses major device number '100'. If + you would like DOC driver to use different major device number, you + can do so by passing "tffs_major=" command line option when + starting the driver. For example, to tell DOC driver to use major + device number '120': + + insmod tffs.ko tffs_major=120 + + ==> NOTE. File Documentation/devices.txt in Linux kernel's directory + list all major device numbers that had been reserved for the + various types of block devices. When specifying major device + number for DOC driver, it is essential to pick the number that + isn't listed in that file as already reserved for some other + block device. Consider using block device numbers that are + allocated for "local/experimental use" (for example, major + block device numbers in 120..127 range). + + + + 5. Board specific configuration options + ======================================= + + 5.1. As shipped, the DOC driver should work with the following boards: + + - Texas Instruments OMAP 2420 ("H4") + - Intel PXA27x Development Platform ("Mainstone") + + If you are using one of these boards, you can skip remaining Sections + in Chapter 5. For all other boards, you will need to configure DOC + driver as appropriate for your system. Instructions below explain how + to do this. + + 5.2. User must tell DOC driver where to look for mDOC. This can be + accomplished by using "tffs_addr=" command line + option, where specifies physical address of the mDOC. + For example, if in your particular board mDOC resides at physical + address 0xc0000000, you would start DOC driver as follows: + + insmod tffs.ko tffs_addr=0xc0000000 + + Alternatively, you can set macro TFFS_PHYS_ADDR in DOC driver's header + tffsarch.h to the physical address of the mDOC, and recompile the + driver. For example, if mDOC device resides at physical address + 0xc0000000, macro TFFS_PHYS_ADDR should be #defined as follows: + + #define TFFS_PHYS_ADDR 0xc0000000 + + In this case you DOC driver by default would look for mDOC at the + specified address, so you can omit "tffs_addr=" + command line parameter, and start DOC driver simply as: + + insmod tffs.ko + + 5.3. When DOC driver starts up, it calls routine tffsarch_init() to do any + board-specific hardware initialization (such as configuring Chip Select + that mDOC is connected to, allocating and configuring DMA channels and + interrupt request lines to be used by DOC driver etc.). The DOC + driver's file tffsarch.c contains example implementations of this + routine for a number of reference boards. + + Users are required to implement this routine as appropriate for their + particular boards. + + 5.4. When DOC driver shuts down, it calls routine TffsHWRelease() to do any + board-specific hardware cleanup (such as releasing previously allocated + DMA channels and interrupt request lines etc.). The DOC driver's file + tffsarch.c contains example implementations of this routine for number + of reference boards. + + Users are required to implement this routine as appropriate for their + particular boards. + + + + 6. Configuring DOC driver to use Direct Memory Access (DMA) + =========================================================== + + 6.1. By default, DOC driver uses software loops to transfer blocks of data + to and from mDOC. In many cases it is possible to substantially improve + mDOC's 'read' performance by using DMA controler to do these data + transfers. + + Current version of DOC driver includes example implementations of DMA + support for the following reference boards: + + - Texas Instruments OMAP2420 ("H4") + - Intel PXA27x ("Mainstone") + + These example implementations are found in DOC driver's files + tffsarch.h and tffsarch.c, and consists of the following items: + + macro flReadEvenNumberOfBytes defined in tffsarch.h + macro flWriteEvenNumberOfBytes defined in tffsarch.h + + routine tffs_dma_init() defined in tffsarch.c + routine tffs_dma_release() defined in tffsarch.c + routine __dmasw_bread() defined in tffsarch.c + routine __dmasw_bwrite() defined in tffsarch.c + + You can use these example implementation as the starting point for DMA + implementation for your own system. + + ===> NOTE. Most likely you will be able to use the definitions of all + macros in file tffsarch.h "as is". You do have to implement + routines in file tffsarch.c as appropriate for your own + system. + + 6.2. To instruct DOC driver to use DMA during 'read' and/or 'write + operations, use 'tffs_dma_mode=' command line option. Possible + values are described below: + + tffs_dma_mode Description + + 1 DMA is used during 'read' operations. + Data is transferred in two steps: first, it is + read (using DMA) from mDOC device into driver's + internal non-cachable DMA buffer; secondly, data + is copied (using memcpy()) from the internal DMA + buffer to destination buffer. + + 2 DMA is used during 'write' operations. + Data is transferred in two steps: first, it is + copied (using memcpy()) from source buffer into + driver's internal non-cacheable DMA buffer; + secondly, data is written (using DMA) from DMA + buffer to mDOC device. + + 3 This is the combination of modes '1' and '2'. + + 5 DMA is used during 'read' operations. + Data is transferred (using DMA) directly from mDOC + device to the destination buffer, without using + intermediate non-cachable DMA buffer. + + 6 DMA is used during 'write' operations. + Data is transferred (using DMA) directly from + the source buffer to mDOC device, without using + intermediate non-cachable DMA buffer. + + 7 This is the combination of modes '5' and '6'. + + ===> NOTE. Systems with fast CPU-to-external-RAM interfaces would benefit + most from the DMA modes 1..3. Systems with slow + CPU-to-external-RAM interfaces (such as PXA27x Mainstone) + would benefit most from the DMA modes 5..7. We advice that you + try various DMA modes with your particular system, and pick + the one with the best I/O performance. + + For example, to instruct DOC driver to use DMA mode '1' during + 'read' operations only, and don't use it during 'write' operations, you + would start the driver as follows: + + insmod tffs.ko tffs_dma_mode=1 + + + + 7. Configuring DOC driver to use mDOC READY interrupt + ===================================================== + + 7.1. The 'write' operations in modern flash devices (such as mDOC) might + take hundreeds of microseconds. Often it is possible to improve overall + system's responsiveness and throughput by configuring DOC driver to + yield CPU during these periods of time. + + ===> NOTE. This option could negatively impact mDOC's "write" + performance, especially when workload on the system + increases. + + 7.2. By default, DOC driver enables mDOC READY interrupt for Intel PXA27x + board ("Mainstone"), and disables it for all other boards. + + To override this default, use 'tffs_irq=' command line option. + The argument specifies board's interrupt request line that mDOC's + IREQ signal is connected to. + + Current version of DOC driver support mDOC interrupts for the following + reference boards: + + +------------------------------------+--------------------+ + | Board | Interrupt | + +------------------------------------+--------------------+ + | Texas Instruments OMAP2420 ("H4") | 190 | + +------------------------------------+--------------------+ + | Intel PXA27x ("Mainstone") | 167 | + +------------------------------------+--------------------+ + + For example, in case of Texas Instruments's OMAP2420 board ("H4"), + mDOC's IRQ signal is connected to board's GPIO_94 line (which generates + interrupt 190), so you would start DOC driver as follows: + + insmod tffs.ko tffs_irq=190 + + To disable mDOC's READY interrupt, specify as '-1'. For example: + + insmod tffs.ko tffs_irq=-1 + + + + 8. Compiling DOC driver + ======================= + + 8.1. This Chapter contains instructions for compiling DOC driver. + + The DOC driver can be placed into the Linux kernel's source code tree, + and compiled as part of the Linux kernel compilation. Section 8.2 + provides instructions of how to do that. + + The DOC driver can also be placed in the separate directory outside of + Linux kernel's source code tree, and compiled separately from the Linux + kernel. Section 8.3 explains how to do that. + + Instructions below refer to the top directory of Linux kernel's source + code tree (where .config kernel configuration file resides) as . + + 8.2. Sections 8.2.1 - 8.2.5 describe how to add DOC driver to Linux kernel's + source code tree, and build it as part of Linux kernel compilation. + + 8.2.1. Create new directory /drivers/tffs, copy DOC driver's archive + to this directory, and unpack it there. + + 8.2.2. If you are using multiple cascaded mDOC devices, edit + /drivers/tffs/flcustom.h file, and uncomment the following + line there: + + #define ATA_MAX_NUM_OF_DEVICES 2 /* only when using casacded devices */ + + 8.2.3. Edit /drivers/Makefile, and add the following statement at the + end of this file: + + obj-y += tffs/ + + This will cause 'make' utility to descend into /drivers/tffs + directory during Linux kernel compilation, build DOC driver, and + statically link it into Linux kernel. + + If you don't want to statically link DOC driver into Linux kernel, + and instead prefer to build it as dynamically loadable kernel module, + you should change this statement as shown below: + + obj-m += tffs/ + + This will cause 'make' utility to descend into /drivers/tffs + directory when building Linux kernel modules, and compile DOC driver + as dynamically loadble Linux kernel. + + 8.2.4. Create /drivers/tffs/Makefile with the following contents: + + obj-y += tffs.o + + tffs-objs := trace32.o + tffs-objs += defs.o + tffs-objs += docdrv.o + tffs-objs += doch_api.o + tffs-objs += doch_ata.o + tffs-objs += dochstub.o + tffs-objs += dochtl.o + tffs-objs += docsys.o + tffs-objs += extfiltr.o + tffs-objs += fatfilt.o + tffs-objs += flbase.o + tffs-objs += flcustom.o + tffs-objs += flioctl.o + tffs-objs += flsystem.o + tffs-objs += hal_nor.o + tffs-objs += tffs2lnx.o + tffs-objs += tffs_api.o + tffs-objs += tffsarch.o + tffs-objs += tffs-pm26.o + tffs-objs += tffsdrv26.o + + This Makefile instructs 'make' utility to build DOC driver, and + statically link it into Linux kernel. + + If you don't want to statically link DOC driver into Linux kernel, + and instead prefer to build it as dynamically loadable kernel module, + you should change the first line of this Makefile as shown below: + + obj-m += tffs.o + + 8.2.5. If you now build Linux kernel (if you have choosen to statically link + DOC driver into Linux kernel) or kernel modules (if you have choosen + to build DOC driver as loadable kernel module), you should see DOC + driver being built as part of this process. + + You are done; skip the rest of Chapter 8. + + 8.3. Sections 8.3.1 - 8.3.5 describe how to build DOC driver in the separate + directory outside of Linux kernel's source code tree, separately from + the Linux kernel. In this case DOC driver will be built as loadable + kernel module tffs.ko. + + 8.3.1. Place DOC driver's archive into the private directory outside of + kernel's source tree, and unpack it there. + + 8.3.2. If you are using multiple cascaded mDOC devices, edit + /drivers/tffs/flcustom.h file, and uncomment the following + line there: + + #define ATA_MAX_NUM_OF_DEVICES 2 /* only when using casacded devices */ + + 8.3.3. DOC driver directory includes example Makefiles for the following + reference boards: + + +------------------------------------+--------------------+ + | Board | Makefile- | + +------------------------------------+--------------------+ + | Texas Instruments OMAP2420 ("H4") | Makefile-omap2420 | + +------------------------------------+--------------------+ + | Intel PXA27x ("Mainstone") | Makefile-pxa27x | + +------------------------------------+--------------------+ + + If you are using one of these boards, then copy the respective file + Makefile- to Makefile. For example, if you are using Texas + Instruments' OMAP2420 board: + + cp Makefile-omap2420 Makefile + + If you are using board other then listed above, you will need to write + your own Makefile. The simplest way to do this is to take any of the + provided reference Makefile-, and change the following macros + as appropriate to your development setup: + + KERNEL_DIR + CC + CFLAGS + LD + LDFLAGS + + The KERNEL_DIR macro should be set to point to top directory of your + kernel's source code tree. + + Macros CC and CFLAGS specify which compiler to use to build DOC driver, + and which compiler flags to use for that. Similarly, macros LD and + LDFLAGS specify which linker to use to link DOC driver's binary, and + which linker flags to use for that. + + ===> NOTE. The easy way to figure out appropriate settings for CC, + CFLAGS, LD and LDFLAGS macros is to execute: + + make V=1 modules + + in the kernel's top directory, and observe the values that + this this command is using to compile and link all Linux + loadable kernel modules. + + The 'V=1' command line option instructs 'make' utility to + issue verbose output (which includes compiler's command line + parameters) rather then terse messages that it produces by + default. + + 8.3.4. Make sure that compiler (as specified by macro CC in Section 8.3.3) + is in the PATH, and build DOC driver by executing: + + make + + in DOC driver's directory. This command should generate tffs.ko + loadable kernel module. + + 8.3.5. You will need to create directory + + lib/modules//kernel/drivers/tffs + + on your target system's root file system, and copy loadable kernel + module tffs.ko to that directory. + + + + 9. Installing DOC driver + ======================== + + 9.1. Add the following line to /lib/modules//modules.dep + file on target's root file system: + + /lib/modules//kernel/drivers/tffs/tffs.ko: + + 9.2. Create mDOC entries for mDOC devices under /dev directory. + + Since current version of DOC driver supports up to 12 "disks" on mDOC + device, with up to 15 file system partition on each of such "disks", + you will need to create up to 192 mDOC entries under /dev (one "raw + disk" entry is required for each of 16 "disk"). You can use script + make_tffs_nodes.sh to create all these /dev entries, or you can do + that manually using Linux 'mknod' utility. For example: + + # mknod /dev/tffsa b 100 0 + # mknod /dev/tffsa1 b 100 1 + # mknod /dev/tffsa2 b 100 2 + # mknod /dev/tffsa3 b 100 3 + # mknod /dev/tffsa4 b 100 4 + + ===> NOTE. If you have configured DOC driver to use different major + device number (see Section 4.1), you will need to replace + '100' in the commands above accordingly. + + These /dev entries refer to: + + /dev/tffsa is the "raw disk" entry for the first mDOC "disk" + /dev/tffsa1 refers to 1-st file system partitions on this disk + /dev/tffsa2 refers to 2-nd file system partitions on this disk + /dev/tffsa3 refers to 3-rd file system partitions on this disk + /dev/tffsa4 refers to 4-th file system partitions on this disk + + ===> NOTE. While there is rarely a need to have more then four file + system partitions on mDOC, DOC driver actually supports + up to 15 of such partitions. If you opted to have more then + four file system partitions, simply add more 'mknod' commands + to the script above to create device entries for additional + partitions. + + ===> NOTE. Current version of mDOC driver doesn't take advantage of + devFs ability to allocate major driver numbers and create + device entries under /dev dynamically. + + + + 10. Using DOC driver + ==================== + + 10.1. The DOC driver can be loaded in the same way that other kernel modules + are loaded: + + insmod tffs.ko [params] + + The following command line parameters are currently supported by DOC + driver: + + tffs_major major device number to use (default is '100') + tffs_addr physical address of mDOC + tffs_sg_read "gather" data during read operations + tffs_sg_write "scatter" data during write operations + tffs_irq IRQ (interrupt request line) to use; '-1' for none + tffs_dma_mode DMA mode (default is don't use DMA) + tffs_pio polled I/O mode + prio controls priority of driver's I/O processing thread + hardsect size of the hardware sector in bytes + rahead read-ahead parameter + fl_debug controls verbosity level of driver's debug messages + tffs_dpd_timeout delay before mDOC automatically enters powerdown mode + + 10.2. To create disk partition table on mDOC: + + fdisk /dev/tffsa + + When 'fdisk' utility presents you with command prompt, you can choose + 'p' to print existing disk partition table, 'd' to delete existing disk + partitions (if exists), or 'n' to create new disk partitions. + + 10.3. If you created new disk partitions in Section 10.2, you will need to + initialize file systems on these disk partition(s). For example, + to initialize EXT2 file system on the first partition (/dev/tffsa1), + use: + + mke2fs /dev/tffsa1 + + When initializing file system on mDOC disk partition, 'mke2fs' utility + calculated file system's block size based on the size of this disk + partition. Currently EXT2 and EXT3 file systems supports file system + blocks of 1024, 2048 and 4096 bytes. Smaller file system blocks (1024 + bytes) allow more efficient use of disk space, at the expense of DOC + driver's 'write' performance. Larger file system blocks (4096 bytes) + noticably increase 'write' performance, at the expense of some disk + space. You can pass '-b ' parameter to 'mke2fs' utility to + explicitely specify size of file system blocks. + + For example, if you want to maximize 'write' performance of DOC driver, + you can do so by telling 'mke2fs' to use largest possible (4096 bytes) + file system blocks: + + mke2fs -b 4096 /dev/tffsa1 + + 10.4. Create mount point for mDOC partition(s), and mount them: + + mkdir -p /mnt/tffsa1 + mount /dev/tffsa1 /mnt/tffsa1 + + 10.5. You can now create files and directories on mDOC. For example: + + echo have a nice day > /mnt/tffsa1/greetings.txt + + To see if the above command worked as expected, execute: + + cat /mnt/tffsa1/greetings.txt + + 10.6. Before shutting the system down, unmount all previously mounted mDOC + partition(s): + + umount /dev/tffsa1 + + + + 11. Configuring DOC driver to reduce power consumption + ====================================================== + + 11.1. This Chapter is only relevant to devices where power conservation is of + major concern. Various battery powered systems (such as mobile phones + and PDAs) fall into this category. + + 11.2. The mDOC device automatically switches from the normal power state into + the low-power state after certain amount of time passes from the + completion of the last read/write access to mDOC device. By default, + this power-down timeout is set to 100 milliseconds; it can be changed + via driver's command line option "tffs_dpd_timeout=". The argument + specifies duration of power-down timeout in milliseconds, for + example: + + insmod tffs.ko tffs_dpd_timeout=1000 + + would cause mDOC device to automatically power itself down one second + (1000 milliseconds) after the last read/write access. + + ===> NOTE. Currently mDOC firmware rounds down power-down timeout to + nearest 100 millisecons multiple, i.e. "tffs_dpd_timeout=345' + has the same effect as "tffs_dpd_timeout=300". + + 11.3. DOC driver supports standard Linux 2.6 power management scheme (option + CONFIG_PM in kernel's .config configuration file). The relevant power + suspend/resume code resides in file tffs-pm26.c, and is + self-explanatory. + + + + 12. Improving DOC driver's I/O performance + ========================================== + + 12.1. This Chapter provides overview of the various means of improving + 'read' and 'write' performance of DOC driver. + + 12.2. The duration of the access cycles to mDOC's registers is one of the + major factors affecting both 'read' and 'write' performance of + DOC driver. The duration of these access cycles is usually + determined by the settings of board's Chip Select that mDOC device + is connected to. If duration of these access cycles substantially + exceeds timings specified in documentation for your mDOC device, + 'write' and especially 'read' performance of DOC driver will be + sub-optimal. + + 12.3. It is possible to improve I/O performance of DOC driver by enabling + compiler optimizations when compiling DOC driver. + + If you have choosen to place DOC driver into Linux kernel's source code + tree (see Section 8.2), you can instruct compiler to optimize generated + code by adding the following line to DOC driver's Makefile: + + EXTRA_CFLAGS := -O2 + + If you have choosen to build DOC driver outside of the Linux kernel's + source code tree (see Section 8.3), you can instruct compiler to + optimize generated code by adding the following line to DOC driver's + Makefile: + + CFLAGS += -O2 + + 12.4. For portability reasons, Linux drivers use dedicated macros and routines + to access registers of peripheral devices. By default DOC driver + adheres to this policy. However, in many cases it is possible to + substantially increase performance of DOC driver by instructing it + to use general purpose memory routines (such as memcpy()) to transfer + blocks of data to and from mDOC device. To do so, use driver's + "tffs_memcpy=1" command line option: + + insmod tffs.ko tffs_memcpy=1 + + ===> NOTE. The "tffs_memcpy=1" command line option might not work + with some boards. + + 12.5. If you are using any of the following reference boards: + + - Texas Instruments's OMAP2420 ("H4") + - Intel PXA27x ("Mainstone") + + you can substantially improve DOC driver's 'read' performance by + telling it to use DMA to transfer data between mDOC and main memory. + See Chapter 6 for more details on "tffs_dma_mode=" command + line option. + + If you are using different board, consider adding support for your + specific DMA implementation to DOC driver. + + 12.6. By default, DOC driver attempts to internally combine few 'write' + requests into single 'write' operation on mDOC device (this process is + usually referred to as "gathering" of I/O requests). Similarly, DOC + driver attempts to internally combine few 'read' requests into single + 'read' operation on mDOC device (this process is usually referred to as + "scattering" of I/O requests). + + While this behavior improves DOC driver's performance for many + systems, it might actually reduce it in case of systems with slow + access to DRAM (such as Intel PXA27x "Mainstone"). For this kind of + systems, it is possible to improve DOC driver's performance by + instructing driver not to perform any scattering/gathering of I/O + requests. + + To tell DOC driver not to combine (gather) 'write' requests, use + command line option "tffs_sg_write=0": + + insmod tffs.ko tffs_sg_write=0 + + To tell DOC driver not to combine (scatter) 'read' requests, use + command line option "tffs_sg_read=0": + + insmod tffs.ko tffs_sg_read=0 + + Use both of these command line options to tell DOC driver not to do + any scattering/gathering of I/O requests: + + insmod tffs.ko tffs_sg_write=0 tffs_sg_read=0 + + 12.7. By default, DOC driver uses polled I/O mode, and transfers single + sector (512 bytes) at a time. It is possible to improve driver's + I/O performance by instructing it to transfer multiple sectors a time. + This could be done by using "tffs_pio=" command line option, where + is either 2 (for two-sector transfers) or 4 (for four-sector + transfers). For example: + + insmod tffs.ko tffs_pio=4 + + 12.8. It is possible to substantially improve DOC driver's 'write' performance + by increasing file system's block size. In case of EXT2 file systems, + file system's block size is determined by 'mke2fs' utility when it + initializes file system on the disk partitions (see Section 10.3), and + is set to 1024, 2048 or 4096 bytes depending on the size of this disk + partition. Passing '-b 4096' command line option to 'mke2fs' utility + forces it to use 4096-byte blocks (the largest possible file system + block size) regardless of the actual size of the disk partition, + therefore improving DOC driver's 'write' performance. + + + 13. Reducing DOC driver's load on CPU + ===================================== + + 13.1. During 'write' operations DOC driver normally polls mDOC device in + order to detect completion of the operation. While this approach allows + DOC driver to maximize mDOC's 'write' performance, it also ties up CPU + for extensive periods of time, reducing amount of CPU time available to + all other processes in the Linux system. + + The alternative approach for DOC driver would be to yield CPU right + after starting 'write' operation on mDOC device, and sleep until + completion of this operation. While this approach is optimal in terms + of minimizing DOC driver's load on CPU, it is only possible if + DOC driver supports mDOC interrupt generation on your particular + system. + + See Chapter 7 for more details regarding mDOC interrupts. + + 13.2. If mDOC interrupt isn't supported for your particular board, it is still + possible to reduce DOC driver's load on CPU by using the command line + option "tffs_skip_sleeps=", where values depend on the type of + mDOC device. You should specify values equal to or greater then + 100. Greater values will improve DOC driver's 'write' + performance, but will also increase it's load on CPU. The optimal + value depends on the desired tradeoff between 'write' performance and + load on CPU. You can start by trying set to 5000: + + insmod tffs.ko tffs_skip_sleeps=5000 + + and measure DOC driver's 'write' performance, and it's load on CPU. + If DOC driver's load on CPU will be acceptable but it's 'write' + performance is too low, try increasing value. If DOC driver's + load on CPU will be too high, try decreasing value until you + reduced the load on CPU to the desired level. + + + + 14. Access to DOC driver's Extended Functions + ============================================= + + 14.1. In addition to standard block device functionality, DOC driver provides + access to DOC driver's Extended Functions, which is not a part of the + standard file system API. See included manual "DOC Driver Extended + Functions Developer Guide" for detailed explanation of all DOC driver's + Extended Functions. + + ===> NOTE. For security reasons, FL_IOCTL_DELETE_SECTORS Extended + function was disabled in the current version of DOC + driver. + + The following section describes only the functionality that is not + supported by DOC drivers for other operating systems. + + Your application code which utilizes DOC driver's IOCTLs, should contain + the following: + + #include "tffsioct.h" + + Your application's Makefile should add DOC driver's headers to + compiler's include path. For example, if you added DOC driver to + kernel's source tree (see Section 8.2): + + -I/drivers/tffs + + The 'ioctl_example' sub-directory in DOC driver archive contains + example application code which shows how to access Extended Functions + via IOCTL calls to DOC driver. + + 14.2. IOCTL limitations + + 14.2.1. All pointers in IOCTL structures should be valid values or null, even + if not used in IOCTL. + + 14.2.2. For FL_IOCTL_FLASH_FORMAT call, 'volumeLabel, 'embeddedSIC' and + 'progressCallback' fields of formatParams must be NULL. The DOC + driver must be restarted right after calling this IOCTL. + + 14.2.3. The FL_IOCTL_SET_ACCESS_ROUTINE and FL_IOCTL_GET_ACCESS_ROUTINE are + not supported. + + + + 15. Formatting mDOC + =================== + + 15.1. The easiest way to format mDOC is to start DOC driver with + "tffs_format=" command line parameter. The argument + specifies which mDOC to format; it is usually specified as zero: + + insmod tffs.ko tffs_format=0 + + In this case DOC driver will re-format mDOC using standard formatting + parameters. + + 15.2. If you are interested in formatting mDOC using custom formatting + parameters, you can accomplish this using FL_IOCTL_FLASH_FORMAT mDOC + Extended Function. See Chapter 14 for more information on mDOC + Extended Functions. + + 15.3. Although not mandatory, it's a good idea to reset mDOC (for example + by rebotting the system) right after formatting it. + + + + 16. Updating firmware in mDOC devices + ===================================== + + 16.1. DOC driver comes with the utility program 'doch-firmware' which can be + used to upgrade firmware in mDOC devices. The source code and Makefile + for this utility program reside in subdirectory 'doch-firmware' in DOC + driver's archive. + + 16.1.1. By default, doch-firmware/Makefile assumes XScale compiler + 'iwmmxt_le-gcc'. If you are using different compiler, change + definition of macro 'CC' in this Makefile accordingly. + + 16.1.2. You will need to change definition of macro 'INCLUDE_DIR' in + doch-firmware/Makefile to point to the directory where all your + applications #include .h files from. + + ===> NOTE. The applications' 'INCLUDE_DIR' is different from + the your kernel's /include directory that is used + in kernel builds. For example, header + exists in the former but not in the latter directories. + + 16.1.3. Change to 'doch-firmware' subdirectory, and build 'doch-firmware' + utility program: + + cd doch-firmware + make + + 16.1.4. Copy doch-firmware/doch-firmware utility program to the + appropriate location on the target's root file system, and + set permissions accordingly. For example: + + cp doch-firmware /sbin + chmod 750 /sbin/doch-firmware + + 16.2. Login to the target as superuser ("root"), and verify that DOC driver is + loaded and running. + + 16.3. Copy mDOC firmware file to the target. + + 16.4. To prevent corruption of the file systems that reside on mDOC, + unmount previously mounted mDOC partition(s) (see Chapter 10 + for more details on mouting mDOC partition(s)). + + 16.5. Execute: + + /sbin/doch-firmware /dev/tffsa + + where is mDOC firmware file (see Section 16.3). + + 16.6. Reset target system to put new mDOC firmware into effect. + + + + 17. Memory footprint + ==================== + + 17.1. This Section describes DOC driver's memory footprint (amount of RAM + that DOC driver's code and data take at runtime) for the reference + case of Intel's PXA27x ("Mainstone") board (ARM processer). DOC + driver's memory footprint varies significabtly between various + processor architectures and compiler optimizations. + + In case of Intel's PXA27x ("Mainstone") board, if compiled without + any optimizations, DOC driver takes about 240 KB of kernel memory + for it's code and data. + + In addition to the above, DOC driver may also do the following + dynamic memory allocations if respective runtime configuration + options are enabled: + + - The buffer for internal scatter/gather operations (see + Section 12.6). By default, size of this buffer is 64 KB. + + - If DMA is used (see Chapter 6), DOC driver allocates internal + 4 KB buffer for use with DMA operations. + + + + 18. Known limitations + ===================== + + - Current version of DOC driver limits number of "disks" per mDOC + "socket" to 14. + + - Current version of DOC driver doesn't support FL_IOCTL_GET_INFO + Extended Function on OTW BDTL partitions ("disks"). + + - Current version of DOC driver fails to re-format 16Gbit mDOC + H3 devices that have protected BDTL partitions ("disks") on them. + + - When formatting with flCreateLogicalPartitions + - Minimal size for logical partition is twice flash unit size + - Usable user space is one flash unit size less than allocated (FAT + alignment overhead) + + Device Minimal Partition Size Overhead + + mDOC H3 128MB and MCP45 512 KB 256KB + mDOC H3 1GB 4 MB 2MB + mDOC H3 2GB 8 MB 4MB + + - More than one device of mDOC H3 in one system is not supported. + + - Using PortaDOC when DOC is configured for 128KB window, requires flSystem + adaptation. + + - IPL size in normal mode 128KB window should not exceed 8KB. + This limitation is not applicable to paged RAM mode and Virtual mode. + + - The field fastAreaLength in structure BDTLPartitionFormatParams3 must + always be set to zero (already set to zero in SDK default). + + - Burst mode not supported. + + - In MCP45: DOCH_IM_IDLE and DOCH_IM_DPD disables AutoDPD. Selecting + DOCH_IM_IDLE_2_DPD (default) is required in order to have autoDPD enabled. + + - In MCP45: Inserting wrong key to a protected partition more than 16 + times will cause rejection of any further attempt until host reset. + + - When using 8KB memory window, only boot from lowest mDOC address + (mDOC base address, typically address zero) is supported. + Boot from top address (mDOC base address + 0x1ffe) is not supported, as mDOC + top address range (0x1800-0x1ffe) does not alias IPL in this mode. + + - flIdentifyProtection will return flHWProtection when the requested + partition is RW protected and the key is not inserted. + + + + 19. Disclaimer of Liability + =========================== + + SanDisk IL Ltd.'s general policy does not recommend the use of its products + in life support applications wherein a failure or malfunction of the + product may directly threaten life or injury. + Accordingly, in any use of products in life support systems or other + applications where failure could cause damage, injury or loss of life, + the products should only be incorporated in systems designed with + appropriate redundancy, fault tolerant or back-up features. + + SanDisk IL shall not be liable for any loss, injury or damage caused by + use of the Products in any of the following applications: + + Special applications such as military related equipment, nuclear reactor + control, and aerospace + + Control devices for automotive vehicles, train, ship and traffic + equipment + + Safety system for disaster prevention and crime prevention + + Medical-related equipment including medical measurement device. + + + + 20. Contact information + ======================= + + For comments, questions and bug reports, please contact your SanDisk + representative or e-mail us at oemsupport@sandisk.com. + + This document is for information use only and is subject to change + without prior notice. + + SanDisk IL Ltd. assumes no responsibility for any errors that may + appear in this document, nor for incidental or consequential damages + resulting from the furnishing, performance or use of this material. + + SanDisk IL's products are not warranted to operate without failure. + SanDisk IL's general policy does not recommend the use of its products + in life support applications where a failure or malfunction of the + product could cause injury or loss of life. Per SanDisk IL's Terms and + Conditions of Sale, the user of SanDisk IL's products in life support + applications assumes all risk of such use and indemnifies SanDisk IL + against all damages. See "Disclaimer of Liability". Accordingly, in + any use of the Product in life support systems or other applications + where failure could cause injury or loss of life, the Product should + only be incorporated in systems designed with appropriate and + sufficient redundancy or backup features. + + All parts of the SanDisk IL's documentation are protected by copyright + law and all rights reserved. + + Contact your local SanDisk sales office or distributor to obtain the + latest specifications before placing your order. + + (C) 1995-2008 SanDisk IL Ltd. All rights reserved. + + mDOC, DOC, TrueFFS, SureFS, SanDisk and SanDisk logo are registered + trademarks of SanDisk IL Ltd. and SanDisk Corporation, respectively. + Other product names or service marks mentioned herein may be trademarks + or registered trademarks of their respective owners and are hereby + acknowledged. diff -urN linux-2.6.30.4-orig/drivers/block/tffs/tffs2lnx.c linux-2.6.30.4/drivers/block/tffs/tffs2lnx.c --- linux-2.6.30.4-orig/drivers/block/tffs/tffs2lnx.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/tffs2lnx.c 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,1764 @@ +/****************************************************************************** + * * + * Project: DOC Driver for Linux 2.6 Block device driver for mDOC H3 family * + * of devices under Linux kernel 2.6. * + * * + * Version: 1.0 * + * Email questions to: oemsupport@sandisk.com * + * Copyright (C) SanDisk IL Ltd. 1995 - 2007 * + * SanDisk IL Ltd., 7 Atir Yeda Street, Kfar Saba 44425, Israel * + * * + ****************************************************************************** + * * + * 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 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, which is set forth in the readme.txt file. * + * 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., 51 * + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + * * + * This License does not grant you any right to use the trademarks, service * + * marks or logos of SanDisk IL Ltd. or SanDisk Corporation. * + * Subject to the foregoing, SanDisk IL Ltd., for itself and on behalf of its * + * licensors, hereby reserves all intellectual property rights in the program,* + * except for the rights expressly granted in this License. * + * * + ******************************************************************************/ + +/* + * $Log$ + */ + +#include "tffsdrv.h" +#include "tffs2lnx.h" +#include "_tffsioct.h" + +#include "fatfilt.h" +#include "flioctl.h" +#include "blockdev.h" +#include "doch_api.h" +#include "doch_ata.h" +#include "defs.h" + + +#define USE_FAT_FILTER /* allow runtime enabling/disabling of FAT filter */ +#define USE_EXT_FILTER /* allow runtime enabling/disabling of EXT filter */ + +#include "extfiltr.h" + + +/* + * global vars + */ + +TffsInfo tffsInfo; + + + +/* + * static routines + */ + +static int /* __init */ init_socket (SocketInfo *pSocket); +static int /* __init */ init_disk (DeviceInfo *pDisk, SocketInfo *pSocket); +static int release_socket (SocketInfo *pSoc); +static int release_disk (DeviceInfo *pDevice); +static void set_disk_geometry (DeviceInfo *pDevice); +static FLStatus socket_std_format (SocketInfo *psoc); +static FLStatus socket_unformat (SocketInfo *psoc); +static FLStatus print_firmware_string (void); +static int ata_passthrough (DeviceInfo *pdev, flIOctlRecord *ioctl_rec_ptr, + flInputLnxRecord *lnx_inrec_ptr); + +#if defined(DOCH_USE_BURST_MODE_READ) || defined(DOCH_USE_BURST_MODE_WRITE) + +/* Command line parameter "tffs_burst_enabled=1" enables synchronous + * burst in DiskOnChip. In this case user might also want to specify + * other burst-releated command-line parameters: + * + * "tffs_burst_length=" + * "tffs_burst_latency=" + * "tffs_burst_hold=" + * "tffs_burst_ws=" + */ + int tffs_burst_enabled = FALSE; + module_param(tffs_burst_enabled, int, S_IRUGO); + MODULE_PARM_DESC(tffs_burst_enabled, "enable (1) or disable (0) synchronous burst."); + + int tffs_burst_length = 5; + module_param(tffs_burst_length, int, S_IRUGO); + MODULE_PARM_DESC(tffs_burst_length, "burst length (2..5)."); + + int tffs_burst_latency = 0; + module_param(tffs_burst_latency, int, S_IRUGO); + MODULE_PARM_DESC(tffs_burst_latency, "burst latency (0..7)."); + + int tffs_burst_hold = 0; + module_param(tffs_burst_hold, int, S_IRUGO); + MODULE_PARM_DESC(tffs_burst_hold, "burst hold (0 or 1)."); + + int tffs_burst_ws = 0; + module_param(tffs_burst_ws, int, S_IRUGO); + MODULE_PARM_DESC(tffs_burst_ws, "burst wait states (0..3)."); + +#endif /* DOCH_USE_BURST_MODE_READ || DOCH_USE_BURST_MODE_WRITE */ + +/* Command line parameter "tffs_hardsect=", when specified as non-zero, + * forces DiskOnChip driver to use this hardsector size rather then obtain it + * from the DiskOnChip. The must be either zero (default - obtain + * hardsector from DiskOnChip), or power of 2 in the range [512..4096]. + */ +static int tffs_hardsect = 0; /* zero - obtain hardsector from DiskOnChip */ +module_param(tffs_hardsect, int, S_IRUGO); +MODULE_PARM_DESC(tffs_hardsect, "Size (in bytes) of hardware sector for all devices."); + +/* Command line parameter "tffs_unformat=" allows user to return + * DiskOnChip to it's original factory state. + * For example: + * + * insmod tffs.o tffs_unformat=0 + * + * will unformat DiskOnchip socket #0. + */ +static int tffs_unformat = 0xff; /* 0xff: don't unformat anything */ +module_param(tffs_unformat, int, S_IRUGO); +MODULE_PARM_DESC(tffs_unformat, "Unformat DiskOnChip socket."); + +/* Command line parameter "tffs_format=" allows user to perform + * low-level formatting of specified DiskOnChip socket when driver starts up. + * For example: + * + * insmod tffs.o tffs_format=0 + * + * will re-format DiskOnchip socket #0. + */ +static int tffs_format = 0xff; /* 0xff: don't format anything */ +module_param(tffs_format, int, S_IRUGO); +MODULE_PARM_DESC(tffs_format, "Format DiskOnChip socket."); + +/* Command line parameter "tffs_pio=", when specified as non-zero, + * forces DiskOnChip driver to use multi-sector polled I/O transfers with + * DiskOnChip H3 devices. The must be in range [0..256]; it specifies + * maximum number of sectors that can be written to or read from DiskOnChip + * H3 device in a single transfer. Default value is zero (use single-sector + * polled I/O mode). + */ +static unsigned int tffs_pio = 0; /* zero for single-sector polled I/O */ +module_param(tffs_pio, int, S_IRUGO); +MODULE_PARM_DESC(tffs_pio, "Multi-sector polled I/O mode."); + +#if defined(USE_FAT_FILTER) || defined(USE_EXT_FILTER) + /* Command line parameter "tffs_fs_filter=" allows user to enable/disable + * various file system filters at runtime. Allowed values for are zero + * (default - don't use filters), '1' (use EXT filter), and '2' (use FAT filter). + */ + static int tffs_fs_filter = 0; /* zero - don't use file system filters */ + module_param(tffs_fs_filter, int, S_IRUGO); + MODULE_PARM_DESC(tffs_fs_filter, "Enable FAT (tffs_fs_filter=1) or EXT (tffs_fs_filter=2) file system filters."); +#endif + + + + + + +unsigned char TffsIsWriteProtected (DeviceInfo *pDevice) +{ +#ifdef HW_PROTECTION + IOreq ioreq; + FLStatus stat; + + ioreq.irHandle = pDevice->bHandle; + + if ((stat = flIdentifyProtection(&ioreq)) == flOK) + { + if ((ioreq.irFlags & WRITE_PROTECTED) && !(ioreq.irFlags & KEY_INSERTED)) + return 1; + } + else + { + if ((stat != flFeatureNotSupported) && (stat != flNotProtected)) + { PrintkDebug ("flIdentifyProtection() error %d", stat); } + } +#endif /* HW_PROTECTION */ + + return 0; +} + + + + +/******************************************************************************* + * * + * T f f s I n i t * + * * + * Initialize TrueFFS, and find all disks on all DiskOnChip sockets. * + * * + * Parameters: none * + * * + * Returns: total number of disks found on all DiskOnChip sockets (zero if * + * none found), or -1 if error occurred. * + * * + *******************************************************************************/ + +int /* __init */ TffsInit (void) +{ + register int iSoc; + FLStatus stat; + +#if (ATA_MAX_NUM_OF_DEVICES != 1) + PrintkInfo ("configured for cascaded mDOC devices"); +#endif + + tffsInfo.wDevices = 0; + + memset (tffsInfo.ppDevices, 0, sizeof(tffsInfo.ppDevices)); + + /* initialize TrueFFS, and find all DiskOnChip sockets */ + if ((stat = flInit()) != flOK) + { + PrintkDebug ("flInit() error %d", stat); + return -1; + } + + /* if in verbose mode, print out DiskOnChip firmware info */ + if (fl_debug > FL_DEBUG_DEF) + print_firmware_string (); + + /* find all disks on all DiskOnChip sockets */ + for (iSoc = 0; iSoc < FL_SOCKETS; iSoc++) + init_socket (&tffsInfo.sockets[iSoc]); + + /* return total number of disks on all DiskOnChip sockets */ + return tffsInfo.wDevices; +} + + + + +/******************************************************************************* + * * + * T f f s C l e a n u p * + * * + * Uninitialize TrueFFS, and shut it down. * + * * + * Parameters: none * + * * + * Returns: always zero (success). * + * * + *******************************************************************************/ + +int TffsCleanup (void) +{ + register int iSoc; + + for (iSoc = 0; iSoc < FL_SOCKETS; iSoc++) + release_socket (&tffsInfo.sockets[iSoc]); + + memset (tffsInfo.ppDevices, 0, sizeof(tffsInfo.ppDevices)); + + tffsInfo.wDevices = 0; + +#ifdef FL_EXIT + flExit(); +#endif + + return 0; +} + + + + +static +int /* __init */ init_socket (SocketInfo *pSoc) +{ + IOreq ioreq; + FLStatus stat; + register int iDev; + SocketInfo*pS; + +#ifdef TFFS_USE_RAM + pSoc->fFound=1; +#endif + + /* if socket wasn't found, abort */ + if (pSoc->fFound == 0) + { pSoc->bHandle = 0xff; return 0; } + + for(pS=tffsInfo.sockets;pS!=pSoc;pS++) + { + if(pSoc->bHandle==pS->bHandle) + pSoc->bHandle++; + } + + PrintkInfo("Socket %u in addr 0x%lx",pSoc->bHandle,pSoc->dwPhysAddr); + + /* if requested, unformat socket */ + if (pSoc->bHandle == tffs_unformat) + { + PrintkInfo("unformat socket %d", tffs_unformat); + if( (stat = socket_unformat(pSoc)) != flOK ) + { + PrintkError ("unformat failed on socket %d, error %d", tffs_unformat, stat); + return 0; + } + PrintkInfo("unformatting successful"); + } + + /* if requested, format socket using standard formatting parameters */ + if (pSoc->bHandle == tffs_format) + { + PrintkInfo("format socket %d", tffs_format); + if( (stat = socket_std_format(pSoc)) != flOK ) + { + PrintkError ("format failed on socket %d, error %d", tffs_format, stat); + return 0; + } + PrintkInfo("formatting successful"); + } + + /* find out how many disks are on this DiskOnChip socket */ + ioreq.irHandle = pSoc->bHandle; + + stat = flCountVolumes(&ioreq); + if ((stat != flOK) || (ioreq.irFlags == 0)) + { + PrintkDebug("flCountVolumes error %d irFlags %lu", (int)stat, ioreq.irFlags); + +#ifdef TFFS_ALLOW_UNFORMATTED + pSoc->wDevices = 1; +#else + pSoc->wDevices = 0; +#endif + } + else + pSoc->wDevices = ioreq.irFlags; + + if (pSoc->wDevices == 0) + { + /* There are no any disk on this socket; probably this + * socket has never been formatted. + */ + return 0; + } + + if ((pSoc->pDevices = KMalloc(pSoc->wDevices * sizeof(DeviceInfo))) == NULL) + { + pSoc->wDevices = 0; + return 0; + } + + for (iDev = 0; iDev < pSoc->wDevices; iDev++) + init_disk (&pSoc->pDevices[iDev], pSoc); + + /* If configured, allocate scatter/gather buffer. Align size + * of scatter/gather buffer up to multiple of PAGE_SIZE. + */ + if (tffs_sg_bufsize > 0) + { + tffs_sg_bufsize = (((tffs_sg_bufsize - 1) / PAGE_SIZE) + 1) * PAGE_SIZE; + + if ((pSoc->pCache = KMalloc(tffs_sg_bufsize)) == NULL) + { + PrintkError ("can't allocate scatter/gather buffer"); + tffs_sg_bufsize = 0; + } + } + +#if 0 /* enable h/w DMA in DiskOnChip */ + ioreq.irHandle = pSoc->bHandle; + ioreq.irFlags = FL_DMA_TYPE; + ioreq.irLength = FL_DMA_HW_ENABLED; + + flHwConfig (&ioreq); +#endif + + /* set single- or multi-sector polled I/O mode */ + TffsSetPIO (pSoc); + +#if 0 /* andrayk June 23 2006: added for H3 burst */ + set_burst (pSoc); +#endif + + return (pSoc->wDevices != 0); +} + + + +/* defice still dismounted after init */ +static +int /* __init */ init_disk (DeviceInfo * pDisk, SocketInfo * pSocket) +{ + unsigned char bDevice; + + pDisk->bHandle=pSocket->bHandle+((pDisk-pSocket->pDevices)<<4); + pDisk->pSocket=(SocketInfo*)pSocket; + pDisk->wTffsHWSectorSizeShift=0; + while( (1<wTffsHWSectorSizeShift) != 8 ) + pDisk->wTffsHWSectorSizeShift++; + if(tffs_hardsect > 0) + pDisk->wHWSectorSize=tffs_hardsect; + else + pDisk->wHWSectorSize=512<<(TFFS_MAXHW_SECTOR_SIZE_BITSwTffsHWSectorSizeShift?TFFS_MAXHW_SECTOR_SIZE_BITS:pDisk->wTffsHWSectorSizeShift); + if(pDisk->wHWSectorSize>4096) + pDisk->wHWSectorSize=4096; + + pDisk->dwSize=0; + pDisk->fAbsMounted=0; + + if(TffsOpenDevice(pDisk)) + { + IOreq ioreq; + FLStatus stat; + + ioreq.irHandle=pDisk->bHandle; + + if ((stat = flSectorsInVolume(&ioreq)) == flOK) + pDisk->dwSize=ioreq.irLength; + else + PrintkDebug("flSectorsInVolume error %d",stat); + } + else + PrintkDebug("TffsOpenDevice error"); + +#ifndef TFFS_ALLOW_UNFORMATTED + if(pDisk->dwSize > 0) + { +#endif + for(bDevice=0; (tffsInfo.ppDevices[bDevice] != NULL) && (bDevice < FL_VOLUMES); bDevice++) + ; + if (bDevice >= FL_VOLUMES) + return 0; + tffsInfo.ppDevices[bDevice]=pDisk; + tffsInfo.wDevices++; + pDisk->diskNo=bDevice; +#ifndef TFFS_ALLOW_UNFORMATTED + } + else + return 0; +#endif + +#ifdef USE_EXT_FILTER + /* if we are going to use EXT filter, install it */ + if ((tffs_fs_filter == 1) && (pDisk->dwSize != 0)) + { + ExtFilterInit (pDisk); + } +#endif + + set_disk_geometry (pDisk); + + PrintkInfo ("Device 0x%x: %ld 512-byte sectors, h/w sector %d bytes", + pDisk->diskNo, pDisk->dwSize, pDisk->wHWSectorSize); + PrintkInfo ("C/H/S %u %u %u", pDisk->wCyl, pDisk->bHead, pDisk->bSect); + + return 1; +} + + + + +static +int release_socket (SocketInfo * pSoc) +{ + register int iDev; + + for (iDev = 0; iDev < pSoc->wDevices; iDev++) + release_disk (&pSoc->pDevices[iDev]); + + if (pSoc->pDevices != NULL) + { + kfree (pSoc->pDevices); + pSoc->pDevices = NULL; + } + + pSoc->wDevices = 0; + + /* free scatter/gather cache if was allocated */ + if (pSoc->pCache != NULL) + kfree (pSoc->pCache); + + return 0; +} + + + + +static +int release_disk (DeviceInfo *pDevice) +{ +#ifndef TFFS_ALLOW_UNFORMATTED + if(pDevice->dwSize==0) + return 0; +#endif + +#ifdef USE_EXT_FILTER + /* if we were using EXT filter, uninstall it */ + if ((tffs_fs_filter == 1) && (pDevice->dwSize != 0)) + { + ExtFilterRelease(pDevice); + } +#endif + if(!TffsCloseDevice(pDevice)) + PrintkDebug("TffsCloseDevice() error"); + + pDevice->dwSize=0; + tffsInfo.wDevices--; + return 1; +} + + + + +unsigned char TffsOpenDevice (DeviceInfo * pDisk) +{ + IOreq ioreq; + FLStatus status = flDriveNotAvailable; + + if (pDisk->fAbsMounted == 0) + { + ioreq.irHandle = pDisk->bHandle; + + if ((status = flAbsMountVolume(&ioreq)) == flOK) + pDisk->fAbsMounted = 1; + else + PrintkError("flAbsMountVolume() error %d", status); + } + +#ifdef TFFS_ALLOW_UNFORMATTED + if (pDisk->dwSize == 0) + return 1; +#endif + + return pDisk->fAbsMounted; +} + + + + +unsigned char TffsCloseDevice (DeviceInfo * pDevice) +{ + IOreq ioreq; + FLStatus stat = flDriveNotAvailable; + + if (pDevice->fAbsMounted != 0) + { + ioreq.irHandle = pDevice->bHandle; + + stat = flDismountVolume (&ioreq); + + pDevice->fAbsMounted = 0; + + if (stat != flOK) + { + PrintkDebug("flDismountVolume() error %d", stat); + return 0; + } + } + + return 1; +} + + + +#ifdef TFFS_STATISTIC + +static +void CountAl(DeviceInfo*pDevice,int block,int count,int dir) +{ + int sector=block,sectors=count,noInShared; + + while(sectors) + { + noInShared=(((sector>>pDevice->wTffsHWSectorSizeShift)+1)<wTffsHWSectorSizeShift)-sector; + if(noInShared>sectors) + noInShared=sectors; + if(noInShared==(1<wTffsHWSectorSizeShift)) + { + if(dir==READ) + { + pDevice->stat.dwAlReadShared++; + pDevice->stat.dwAlReadSec+=noInShared; + } + else + { + pDevice->stat.dwAlWriteShared++; + pDevice->stat.dwAlWriteSec+=noInShared; + } + } + else + { + if(dir==READ) + { + pDevice->stat.dwUnalReadShared++; + pDevice->stat.dwUnalReadSec+=noInShared; + } + else + { + pDevice->stat.dwUnalWriteShared++; + pDevice->stat.dwUnalWriteSec+=noInShared; + } + } + sectors-=noInShared; + sector+=noInShared; + } +} + +#endif /* TFFS_STATISTIC */ + + +#ifdef TFFS_COUNT_REQ_SECTORS +extern unsigned long dwRead,dwWritten; +#endif + + + +unsigned char TffsRead(DeviceInfo*pDevice,void*data,int block,int count) +{ + IOreq ioreq; + FLStatus stat = flDriveNotAvailable; + +#ifdef TFFS_COUNT_REQ_SECTORS + dwRead+=count; +#endif + +#ifdef TFFS_STATISTIC + pDevice->stat.dwAbsRead++; + pDevice->stat.dwAbsReadSec+=count; + CountAl(pDevice,block,count,READ); +#endif + + ioreq.irHandle=pDevice->bHandle; + ioreq.irData=data; + ioreq.irLength=block; + ioreq.irCount=count; + + if ((stat = flAbsRead(&ioreq)) == flOK) + return 1; + + PrintkDebug("flAbsRead() error %d",stat); + return 0; +} + +/* Perform read or write of appropriate number of sectors from a DOC volume */ +unsigned char TffsWrite(DeviceInfo*pDevice,void*data,int block,int count) +{ +#ifndef TFFS_RO + IOreq ioreq; + FLStatus stat = flDriveNotAvailable; + +# ifdef TFFS_COUNT_REQ_SECTORS + dwWritten+=count; +# endif + +# ifdef TFFS_STATISTIC + pDevice->stat.dwAbsWrite++; + pDevice->stat.dwAbsWriteSec+=count; + CountAl(pDevice,block,count,WRITE); +# endif + ioreq.irHandle=pDevice->bHandle; + ioreq.irData=data; + ioreq.irLength=block; + ioreq.irCount=count; + +# ifdef USE_EXT_FILTER + if (tffs_fs_filter == 1) /* use EXT filter */ + ExtFilter (pDevice,data,block,count); +# endif + +# ifdef USE_FAT_FILTER + if (tffs_fs_filter == 2) /* use FAT filter */ + ffCheckBeforeWrite (&ioreq); +# endif + if ((stat = flAbsWrite(&ioreq)) == flOK) + return 1; + PrintkError ("flAbsWrite error %d",stat); + +#endif /* TFFS_RO */ + + return 0; +} + + + +/************************************************************************ + * * + * s o c k e t _ s t d _ f o r m a t * + * * + * Formats DiskOnChip socket with standard format parameters. * + * WARNING: all existing data on DiskOnChip is destroyed ! * + * * + * Parameters: * + * psoc : socket to format * + * * + * Returns: * + * flOK on success, otherwise respective error code * + * * + ************************************************************************/ +static +FLStatus socket_std_format (SocketInfo * psoc) +{ + IOreq ioreq; + FLStatus stat = flDriveNotAvailable; + + /* format socket using standard formatting parameters */ + +static FormatParams3 std_fp3 = STD_FORMAT_PARAMS3; +static BDTLPartitionFormatParams3 std_bdtl_fp3 = STD_BDTL_PARAMS3; + + std_fp3.BDTLPartitionInfo = &std_bdtl_fp3; + + ioreq.irHandle = psoc->bHandle; + ioreq.irFlags = TL_NORMAL_FORMAT; + ioreq.irData = &std_fp3; + + if ((stat = flFlashFormat(&ioreq)) != flOK) + PrintkError("flFlashFormat error %d", stat); + + return stat; +} + + + +/************************************************************************ + * * + * s o c k e t _ u n _ f o r m a t * + * * + * Unformats DiskOnChip socket returning it to it's original factory * + * state. * + * WARNING: all existing data on DiskOnChip is destroyed ! * + * * + * Parameters: * + * psoc : socket to unformat * + * * + * Returns: * + * flOK on success, otherwise respective error code * + * * + ************************************************************************/ +static +FLStatus socket_unformat (SocketInfo * psoc) +{ + IOreq ioreq; + FLStatus stat; + + memset (&ioreq, 0, sizeof(ioreq)); + ioreq.irHandle = psoc->bHandle; + + if ((stat = flUnformat(&ioreq)) != flOK) + PrintkError("flUnformat error %d", stat); + + return stat; +} + + + +/************************************************************************ + * * + * p r i n t _ f i r m w a r e _ s t r i n g * + * * + * Print out various firmware informatio. * + * * + * Returns: * + * flOK on success, otherwise respective error code * + * * + ************************************************************************/ +static +FLStatus print_firmware_string (void) +{ + IOreq ioreq; + DOCH_Registers in_regs; + FLByte buf [512]; + FLStatus stat; + + memset (&in_regs, 0 , sizeof(in_regs)); + memset (&buf, 0 , sizeof(buf)); + + ioreq.irPath = &in_regs; + ioreq.irCount = DOCH_PASSTHRU_DATA_IN; + ioreq.irLength = 1; + ioreq.irData = buf; + + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + in_regs.bFeaturesError = DOCH_GET_EXTENDED_DEVICE_INFO; + + if( (stat = flDochPassThrough(&ioreq)) == flOK ) + PrintkInfo("%s", buf); + else + PrintkError("Can't get mDOC firmware info"); + + return stat; +} + + + +/************************************************************************ + * * + * a t a _ p a s s t h r o u g h * + * * + * This routine implements ATA pass-through command for DiskOnChip H3 * + * devices. * + * * + * Parameters: * + * pdev : device * + * ioctl_rec_ptr : kernel copy of user's flIOctlRecord * + * lnx_inrec_ptr : kernel copy of user's flInputLnxRecord * + * * + * Returns: * + * zero on success, otherwise -EFAULT or -ENOMEM * + * * + ************************************************************************/ +static +int ata_passthrough ( DeviceInfo * pdev, + flIOctlRecord * ioctl_rec_ptr, + flInputLnxRecord * lnx_inrec_ptr ) +{ + flOutputLnxRecord lnx_outrec; + flAtaPassthrough ata; + char * buf = NULL; + int rc = -EFAULT; + + /* copy struct flAtaPassthrough from user space */ + if( access_ok(VERIFY_WRITE, (void *)(lnx_inrec_ptr->data), sizeof(ata)) == 0 ) + return -EFAULT; + + if( copy_from_user(&ata, (void *)(lnx_inrec_ptr->data), sizeof(ata)) != 0 ) + return -EFAULT; + + if ((ata.passThruOP == DOCH_PASSTHRU_DATA_OUT) || (ata.passThruOP == DOCH_PASSTHRU_DATA_IN)) + { + /* currently we don't allow more then 256 sectors in single transfer */ + if (ata.userBuffSize > (256 * FL_SECTOR_SIZE)) + return -ENOMEM; + + /* check if we can access user buffer */ + if (ata.passThruOP == DOCH_PASSTHRU_DATA_OUT) + { + if( access_ok(VERIFY_READ, ata.userBuff, ata.userBuffSize) == 0 ) + return -EFAULT; + } + else if (ata.passThruOP == DOCH_PASSTHRU_DATA_IN) + { + if( access_ok(VERIFY_WRITE, ata.userBuff, ata.userBuffSize) == 0 ) + return -EFAULT; + } + + /* allocate kernel buffer to hold user data */ + if ((buf = vmalloc(ata.userBuffSize)) == NULL) + return -ENOMEM; + } + + /* For output (host -> DiskOnChip) operations, copy data from + * user buffer 'ata.userBuff' to to kernel buffer 'buf' + */ + if (ata.passThruOP == DOCH_PASSTHRU_DATA_OUT) + { + if( copy_from_user(buf, ata.userBuff, ata.userBuffSize) != 0 ) + goto quit; + +#if 0 /* andrayk May 12 2006: firmware checksum calculation to assist debugging */ + { register unsigned long s; + register int n = (ata.userBuffSize / sizeof(long)) - 1; + unsigned long * p = (unsigned long *)buf; + + for (s = 0; n >= 0; n--) + s ^= p[n]; + + PrintkDebug ("Firmware file checksum is 0x%lx", s); + } +#endif + } + + /* Execute pass-through ATA command, and put it's status into + * both 'flOutputLnxRecord.status' and 'flAtaPassthrough.status'. + */ + ata.status = lnx_outrec.status = + + DOCHAtaPassThrough (pdev->bHandle, /* not 'ata.socketNum', for security reasons */ + ata.passThruOP, + (DOCH_Registers *) &ata.in_regs, + (DOCH_Registers *) &ata.out_regs, + ata.secNum, + buf, + FALSE); /* don't use DiskOnChip interrupt */ + + /* For input (DiskOnChip -> host) operations, copy data from + * kernel buffer 'buf' to user buffer 'ata.userBuff'. + */ + if (ata.passThruOP == DOCH_PASSTHRU_DATA_IN) + { + if( copy_to_user(ata.userBuff, buf, ata.userBuffSize) != 0 ) + goto quit; + } + + /* copy updated struct flAtaPassthrough back to user space */ + if( copy_to_user((void *)(lnx_inrec_ptr->data), &ata, sizeof(ata)) != 0 ) + goto quit; + + /* copy updated struct flOutputLnxRecord back to user space */ + if( copy_to_user(ioctl_rec_ptr->outputRecord, &lnx_outrec, sizeof(lnx_outrec)) != 0 ) + goto quit; + + rc = 0; /* success */ + + quit: + + if (buf != NULL) + { + memset (buf, 0, ata.userBuffSize); + vfree (buf); + } + + return rc; +} + + + + +#define USR2KRN_O_START(typeOut) \ + { \ + typeOut output; \ + void *tmp; \ + if(!access_ok(VERIFY_WRITE,ioctlRecord.outputRecord,sizeof(typeOut))) \ + return -EFAULT; \ + tmp = ioctlRecord.outputRecord; \ + ioctlRecord.outputRecord = &output; + +#define USR2KRN_IO_START(typeIn,typeOut) \ + { \ + typeIn input; \ + typeOut output; \ + void *tmp; \ + if (!access_ok(VERIFY_READ,ioctlRecord.inputRecord,sizeof(typeIn))) \ + return -EFAULT; \ + if (copy_from_user(&input,ioctlRecord.inputRecord,sizeof(typeIn))) \ + return -EFAULT; \ + ioctlRecord.inputRecord = &input; \ + if (!access_ok(VERIFY_WRITE,ioctlRecord.outputRecord,sizeof(typeOut))) \ + return -EFAULT; \ + tmp = ioctlRecord.outputRecord; \ + ioctlRecord.outputRecord = &output; + +#define USR2KRN_END \ + if (copy_to_user(tmp, &output, sizeof(output))) \ + return -EFAULT; \ + return 0; \ + } + +#define USR2KRN01(theHandle,typeOut,pSoc) \ + USR2KRN_O_START(typeOut) \ + ioreq.irHandle = theHandle; \ + flIOctl(&ioreq); \ + USR2KRN_END + +#define USR2KRN11(theHandle,typeIn,typeOut,pSoc) \ + USR2KRN_IO_START(typeIn,typeOut) \ + ioreq.irHandle = theHandle; \ + flIOctl(&ioreq); \ + USR2KRN_END + + +/* returns: 0 - OK, 1 - no TFFS ioctl, <0 - error */ +int TffsIoctl(DeviceInfo*pDevice,int cmd,unsigned long arg) +{ +#ifdef FL_IOCTL_INTERFACE + unsigned char bdtlVolume=pDevice->bHandle; + IOreq ioreq; + flIOctlRecord ioctlRecord; + + static unsigned int handle_for_ioctls = 0xffff; + + if ((cmd < FL_IOCTL_LNX) || (cmd > FL_IOCTL_IPL_HW_PROTECTION)) + { PrintkError ("unknown IOCTL code %d passed to TrueFFS", cmd); return 1; } + + + /* map flIOctlRecord */ + if(!access_ok(VERIFY_WRITE|VERIFY_READ,(void*)arg,sizeof(flIOctlRecord))) + return -EFAULT; + if(copy_from_user(&ioctlRecord,(void*)arg,sizeof(flIOctlRecord))) + return -EFAULT; + ioreq.irData=&ioctlRecord; + ioreq.irFlags=cmd; + + switch(cmd) + { + + + case FL_IOCTL_GET_INFO: + { + struct hd_geometry geometry; + USR2KRN_O_START(flDiskInfoOutput); + + ioreq.irHandle = bdtlVolume; + flIOctl(&ioreq); + + geometry.heads = pDevice->bHead; + geometry.sectors = pDevice->bSect; + geometry.cylinders = pDevice->wCyl; + + ((flDiskInfoOutput*)(ioctlRecord.outputRecord))->info.cylinders=geometry.cylinders; + ((flDiskInfoOutput*)(ioctlRecord.outputRecord))->info.heads=geometry.heads; + ((flDiskInfoOutput*)(ioctlRecord.outputRecord))->info.sectors=geometry.sectors; + USR2KRN_END; + } + + + case FL_IOCTL_DEFRAGMENT: + USR2KRN11(bdtlVolume,flDefragInput,flDefragOutput,pSoc); + + + case FL_IOCTL_MOUNT_VOLUME: + USR2KRN11(bdtlVolume,flMountInput,flOutputStatusRecord,pSoc); + + +#ifdef BDK_ACCESS + case FL_IOCTL_BDK_OPERATION: + { + void*tmp1=NULL,*tmpIn=NULL; + flBDKOperationInput input; + flOutputStatusRecord output; + void*tmp; + + if(!access_ok(VERIFY_READ|VERIFY_WRITE,ioctlRecord.inputRecord,sizeof(flBDKOperationInput))) + { + PrintkDebug("FL_IOCTL_BDK_OPERATION:access_ok(inputRecord)"); + return -EFAULT; + } + if(copy_from_user(&input,ioctlRecord.inputRecord,sizeof(flBDKOperationInput))) + { + PrintkDebug("FL_IOCTL_BDK_OPERATION:copy_from_user(inputRecord)"); + return -EFAULT; + } + if(!access_ok(VERIFY_WRITE,ioctlRecord.outputRecord,sizeof(flOutputStatusRecord))) + { + PrintkDebug("FL_IOCTL_BDK_OPERATION:access_ok(outputRecord)"); + return -EFAULT; + } + tmp=ioctlRecord.outputRecord; + tmpIn=ioctlRecord.inputRecord; + ioctlRecord.inputRecord=&input; + ioctlRecord.outputRecord=&output; + + if(input.bdkStruct.bdkBuffer!=NULL) + { + tmp1=input.bdkStruct.bdkBuffer; + input.bdkStruct.bdkBuffer=VMalloc(input.bdkStruct.length); + if(input.bdkStruct.bdkBuffer==NULL) + { + PrintkDebug("FL_IOCTL_BDK_OPERATION:vmalloc"); + return -ENOMEM; + } + if(!access_ok(VERIFY_WRITE|VERIFY_READ,tmp1,input.bdkStruct.length)) + { + vfree(input.bdkStruct.bdkBuffer); + PrintkDebug("FL_IOCTL_BDK_OPERATION:access_ok"); + return -EFAULT; + } + if(copy_from_user(input.bdkStruct.bdkBuffer,tmp1,input.bdkStruct.length)) + { + vfree(input.bdkStruct.bdkBuffer); + PrintkDebug("FL_IOCTL_BDK_OPERATION:copy_from_user"); + return -EFAULT; + } + } + + ioreq.irHandle = handle_for_ioctls; + flIOctl(&ioreq); + + if(input.bdkStruct.bdkBuffer!=NULL) + { + if(copy_to_user(tmp1,input.bdkStruct.bdkBuffer,input.bdkStruct.length)) + { + PrintkDebug("FL_IOCTL_BDK_OPERATION:copy_to_user(bdkBuffer)"); + vfree(input.bdkStruct.bdkBuffer); + return -EFAULT; + } + vfree(input.bdkStruct.bdkBuffer); + } + + /* copy flBDKOperationInput */ + input.bdkStruct.bdkBuffer=tmp1; + if(copy_to_user(tmpIn,&input,sizeof(flBDKOperationInput))) + { + if(input.bdkStruct.bdkBuffer!=NULL) + vfree(input.bdkStruct.bdkBuffer); + PrintkDebug("FL_IOCTL_BDK_OPERATION:copy_to_user(inputRecord)"); + return -EFAULT; + } + + if(copy_to_user(tmp,&output,sizeof(output))) + return -EFAULT; + return 0; + } +#endif /* BDK_ACCESS */ + + + case FL_IOCTL_DELETE_SECTORS: + case FL_IOCTL_READ_SECTORS: + case FL_IOCTL_WRITE_SECTORS: + return -EINVAL; + + + case FL_IOCTL_BDTL_HW_PROTECTION: + case FL_IOCTL_IPL_HW_PROTECTION: +#ifdef BDK_ACCESS + case FL_IOCTL_BINARY_HW_PROTECTION: +#endif + +#ifdef HW_PROTECTION + { flProtectionInput my_prot_in, *usr_prot_in = (flProtectionInput *)ioctlRecord.inputRecord; + flProtectionOutput my_prot_out, *usr_prot_out = (flProtectionOutput *)ioctlRecord.outputRecord; + + if( !access_ok((VERIFY_WRITE | VERIFY_READ), usr_prot_in, sizeof(flProtectionInput)) ) + return -EFAULT; + if( !access_ok(VERIFY_WRITE, usr_prot_out, sizeof(flProtectionOutput))) + return -EFAULT; + + if( copy_from_user(&my_prot_in, usr_prot_in, sizeof(flProtectionInput)) ) + return -EFAULT; + + ioctlRecord.inputRecord = &my_prot_in; + ioctlRecord.outputRecord = &my_prot_out; + +# ifdef BDK_ACCESS + if (cmd == FL_IOCTL_BINARY_HW_PROTECTION) + ioreq.irHandle = handle_for_ioctls; + else +# endif + ioreq.irHandle = ((handle_for_ioctls != 0xffff) ? handle_for_ioctls : bdtlVolume); + + flIOctl (&ioreq); + + if( copy_to_user(usr_prot_in, &my_prot_in, sizeof(flProtectionInput)) ) + return -EFAULT; + if( copy_to_user(usr_prot_out, &my_prot_out,sizeof(flProtectionOutput)) ) + return -EFAULT; + + return 0; + } + +#else /* !HW_PROTECTION */ + return -EINVAL; +#endif + + + case FL_IOCTL_OTP: +#ifdef HW_OTP + { + void*tmp1; + void *tmpSize = ioctlRecord.inputRecord; + USR2KRN_IO_START(flOtpInput,flOutputStatusRecord); + tmp1=input.buffer; + input.buffer=KMalloc(input.length); + if(input.buffer==NULL) + return -ENOMEM; + if(!access_ok(VERIFY_WRITE|VERIFY_READ,tmp1,input.length)) + { + kfree(input.buffer); + return -EFAULT; + } + if(copy_from_user(input.buffer,tmp1,input.length)) + { + kfree(input.buffer); + return -EFAULT; + } + + ioreq.irHandle = (bdtlVolume & 0x0f); + flIOctl(&ioreq); + + if (input.type == OTP_SIZE) { + if(copy_to_user(tmpSize,&input,sizeof(flOtpInput))) + { + kfree(input.buffer); + return -EFAULT; + } + } else + if(copy_to_user(tmp1,input.buffer,input.length)) + { + kfree(input.buffer); + return -EFAULT; + } + kfree(input.buffer); + USR2KRN_END; + } +#else /* HW_OTP */ + return -EINVAL; +#endif /* HW_OTP */ + + + case FL_IOCTL_CUSTOMER_ID: +#ifdef HW_OTP + USR2KRN01(bdtlVolume&0x0f,flCustomerIdOutput,pSoc); +#else /* HW_OTP */ + return -EINVAL; +#endif + + + case FL_IOCTL_UNIQUE_ID: +#ifdef HW_OTP + USR2KRN01(bdtlVolume&0x0f,flUniqueIdOutput,pSoc); +#else /* HW_OTP */ + return -EINVAL; +#endif + + + case FL_IOCTL_NUMBER_OF_PARTITIONS: + USR2KRN01(bdtlVolume&0x0f,flCountPartitionsOutput,pSoc); + + + case FL_IOCTL_WRITE_IPL: +#ifndef NO_IPL_CODE + { + flIPLInput iplInput; + flOutputStatusRecord outputStatusRecord; + void*outputStatusRecordSave,*bBufPtrSave; + if(!access_ok(VERIFY_READ,ioctlRecord.inputRecord,sizeof(flIPLInput))) + return -EFAULT; + if(copy_from_user(&iplInput,ioctlRecord.inputRecord,sizeof(flIPLInput))) + return -EFAULT; + if(!access_ok(VERIFY_WRITE,ioctlRecord.outputRecord,sizeof(flOutputStatusRecord))) + return -EFAULT; + outputStatusRecordSave=ioctlRecord.outputRecord; + ioctlRecord.inputRecord=&iplInput; + ioctlRecord.outputRecord=&outputStatusRecord; + + bBufPtrSave=iplInput.bBufPtr; + iplInput.bBufPtr=KMalloc(iplInput.sdwLength); + if(iplInput.bBufPtr==NULL) + return -ENOMEM; + if(!access_ok(VERIFY_READ,bBufPtrSave,iplInput.sdwLength)) + { + kfree(iplInput.bBufPtr); + return -EFAULT; + } + if(copy_from_user(iplInput.bBufPtr,bBufPtrSave,iplInput.sdwLength)) + { + kfree(iplInput.bBufPtr); + return -EFAULT; + } + ioreq.irHandle=bdtlVolume&0x0f; + flIOctl (&ioreq); + + kfree(iplInput.bBufPtr); + if(copy_to_user(outputStatusRecordSave,&outputStatusRecord,sizeof(flOutputStatusRecord))) + return -EFAULT; + return 0; + } +#else /* NO_IPL_CODE */ + return -EINVAL; +#endif /* NO_IPL_CODE */ + + + case FL_IOCTL_DEEP_POWER_DOWN_MODE: + USR2KRN11(bdtlVolume&0x0f,flPowerDownInput,flOutputStatusRecord,pSoc); + + + case FL_IOCTL_EXTENDED_ENVIRONMENT_VARIABLES: +#ifdef FL_ENVIRONMENT_VARS + USR2KRN11(bdtlVolume,flExtendedEnvVarsInput,flExtendedEnvVarsOutput,pSoc); +#else + return -EINVAL; +#endif /* FL_ENVIRONMENT_VARS */ + + + case FL_IOCTL_VERIFY_VOLUME: +#ifdef VERIFY_VOLUME + USR2KRN11(bdtlVolume,flVerifyVolumeInput,flVerifyVolumeOutput,pSoc); +#endif + + + case FL_IOCTL_SET_ACCESS_ROUTINE: + return -EINVAL; + + + case FL_IOCTL_GET_ACCESS_ROUTINE: + return -EINVAL; + + + case FL_IOCTL_IS_QUICK_MOUNT_VALID: +# ifndef FL_NO_QUICK_MOUNT_FEATURE + USR2KRN01(bdtlVolume,flGetQuickMountOutput,pSoc); +# else + return -EINVAL; +# endif /* FL_NO_QUICK_MOUNT_FEATURE */ + + + case FL_IOCTL_WRITE_QUICK_MOUNT_INFO: +# ifndef FL_NO_QUICK_MOUNT_FEATURE + USR2KRN01(bdtlVolume,flOutputStatusRecord,pSoc); +# else + return -EINVAL; +# endif /* FL_NO_QUICK_MOUNT_FEATURE */ + + + case FL_IOCTL_CLEAR_QUICK_MOUNT_INFO: +# ifndef FL_NO_QUICK_MOUNT_FEATURE + USR2KRN01(bdtlVolume,flOutputStatusRecord,pSoc); +# else + return -EINVAL; +# endif /* FL_NO_QUICK_MOUNT_FEATURE */ + + + case FL_IOCTL_FLASH_FORMAT: + +# ifndef FL_FORMAT_VOLUME + return -EINVAL; +# else + { FormatParams3 formatParams3; + BDTLPartitionFormatParams3 bdtl_fp [FL_VOLUMES]; +# ifdef BDK_ACCESS + BinaryPartitionFormatParams3 bin_fp [FL_BINARY_PARTITIONS]; +# endif + flFlashFormatInput flashFormatInput; + flOutputStatusRecord outputStatusRecord; + void * user_outputStatusRecord; + int bdtls; /* BDTL partitions to create */ + int bins; /* binary partitions to create */ + + PrintkDebug("TffsIoctl:FL_IOCTL_FLASH_FORMAT"); + + if( !access_ok(VERIFY_WRITE, ioctlRecord.outputRecord, sizeof(flOutputStatusRecord)) ) + return -EFAULT; + + user_outputStatusRecord = ioctlRecord.outputRecord; + ioctlRecord.outputRecord = &outputStatusRecord; + + if( !access_ok(VERIFY_READ, ioctlRecord.inputRecord, sizeof(flFlashFormatInput)) ) + return -EFAULT; + + if( copy_from_user(&flashFormatInput, ioctlRecord.inputRecord, sizeof(flFlashFormatInput)) ) + return -EFAULT; + + ioctlRecord.inputRecord = &flashFormatInput; + + if( !access_ok(VERIFY_READ, flashFormatInput.fpPtr, sizeof(FormatParams3)) ) + return -EFAULT; + + if( copy_from_user(&formatParams3, flashFormatInput.fpPtr, sizeof(FormatParams3)) ) + return -EFAULT; + + /* BDTL partitions layout */ + bdtls = flashFormatInput.fpPtr->noOfBDTLPartitions; + if (bdtls > FL_VOLUMES) + return -EINVAL; + + if( !access_ok(VERIFY_READ, flashFormatInput.fpPtr->BDTLPartitionInfo, + (sizeof(BDTLPartitionFormatParams3) * bdtls)) ) + return -EFAULT; + + if( copy_from_user(bdtl_fp, flashFormatInput.fpPtr->BDTLPartitionInfo, + (sizeof(BDTLPartitionFormatParams3) * bdtls)) ) + return -EFAULT; + + flashFormatInput.fpPtr->BDTLPartitionInfo = bdtl_fp; + + /* binary partitions layout */ + bins = flashFormatInput.fpPtr->noOfBinaryPartitions; + if (bins > 0) + { +# ifdef BDK_ACCESS + if( !access_ok(VERIFY_READ, flashFormatInput.fpPtr->binaryPartitionInfo, + (sizeof(BinaryPartitionFormatParams3) * bins)) ) + return -EFAULT; + + if( copy_from_user(bin_fp, flashFormatInput.fpPtr->binaryPartitionInfo, + (sizeof(BinaryPartitionFormatParams3) * bins)) ) + return -EFAULT; + + flashFormatInput.fpPtr->binaryPartitionInfo = bin_fp; +# else + return -EINVAL; +# endif + } + + /* set to NULL not mapped pointers */ + flashFormatInput.fpPtr->progressCallback = NULL; + flashFormatInput.fpPtr->embeddedCIS = NULL; + flashFormatInput.fpPtr->embeddedCISlength = 0; + + ioreq.irHandle = (bdtlVolume & 0x0f); + flIOctl (&ioreq); + + if( copy_to_user(user_outputStatusRecord, &outputStatusRecord, sizeof(outputStatusRecord))) + return -EFAULT; + + return 0; + } +# endif /* FL_FORMAT_VOLUME */ + + + case FL_IOCTL_ERASE_BD: +# ifdef FL_FORMAT_VOLUME + PrintkDebug("TffsIoctl:FL_IOCTL_ERASE_BD"); + USR2KRN11(bdtlVolume,flEraseBDInput,flOutputStatusRecord,pSoc); +# else /* FL_FORMAT_VOLUME */ + return -EINVAL; +# endif /* FL_FORMAT_VOLUME */ + + + case FL_IOCTL_FLASH_UNFORMAT: +# ifdef FL_FORMAT_VOLUME + USR2KRN11(bdtlVolume,flFlashUnformatInput,flOutputStatusRecord,pSoc); +# else /* FL_FORMAT_VOLUME */ + return -EINVAL; +# endif /* FL_FORMAT_VOLUME */ + + +#if defined(TFFS_USE_G4) && defined(HW_OTP) + case FL_IOCTL_MCOTP: + { + flMCOtpInput mcotpInput; + flOutputStatusRecord outputStatusRecord; + void*outputStatusRecordSave,*bufferSave=NULL,*mcotpInputSave; + + if(!access_ok(VERIFY_READ|VERIFY_WRITE,ioctlRecord.inputRecord,sizeof(flMCOtpInput))) + return -EFAULT; + if(copy_from_user(&mcotpInput,ioctlRecord.inputRecord,sizeof(flMCOtpInput))) + return -EFAULT; + if(!access_ok(VERIFY_WRITE,ioctlRecord.outputRecord,sizeof(flOutputStatusRecord))) + return -EFAULT; + outputStatusRecordSave=ioctlRecord.outputRecord; + mcotpInputSave=ioctlRecord.inputRecord; + ioctlRecord.inputRecord=&mcotpInput; + ioctlRecord.outputRecord=&outputStatusRecord; + + if(mcotpInput.length!=0) + { + bufferSave=mcotpInput.buffer; + mcotpInput.buffer=VMalloc(mcotpInput.length); + if(mcotpInput.buffer==NULL) + return -ENOMEM; + if(!access_ok(VERIFY_READ|VERIFY_WRITE,mcotpInput.buffer,mcotpInput.length)) + return -EFAULT; + if(copy_from_user(mcotpInput.buffer,bufferSave,sizeof(mcotpInput.length))) + return -EFAULT; + } + + ioreq.irHandle = bdtlVolume&0x0f; + flIOctl (&ioreq); + + if(mcotpInput.length!=0) + { + if(copy_to_user(bufferSave,mcotpInput.buffer,sizeof(mcotpInput.length))) + return -EFAULT; + vfree(mcotpInput.buffer); + mcotpInput.buffer=bufferSave; + } + if(copy_to_user(mcotpInputSave,&mcotpInput,sizeof(flMCOtpInput))) + return -EFAULT; + if(copy_to_user(outputStatusRecordSave,&outputStatusRecord,sizeof(flMCOtpInput))) + return -EFAULT; + + } +#endif /* defined(TFFS_USE_G4) && defined(HW_OTP) */ + + + case FL_IOCTL_LNX: + { + flInputLnxRecord inRec; + flOutputLnxRecord outRec; + + if(!access_ok(VERIFY_READ,ioctlRecord.inputRecord,sizeof(flInputLnxRecord))) + return -EFAULT; + if(copy_from_user(&inRec,ioctlRecord.inputRecord,sizeof(flInputLnxRecord))) + return -EFAULT; + if(!access_ok(VERIFY_WRITE,ioctlRecord.outputRecord,sizeof(flOutputLnxRecord))) + return -EFAULT; + + switch(inRec.command) + { + case 0: /* set TrueFFS handle for future IOCTLs */ + { + handle_for_ioctls = inRec.data; + + outRec.status = flOK; + if(copy_to_user(ioctlRecord.outputRecord, &outRec, sizeof(flOutputLnxRecord))) + return -EFAULT; + return 0; + } +#if defined(TFFS_DEBUG_DRIVER) && !defined(TFFS_RO) + case 3: /* print no of used sectors on device */ + { + ioreq.irHandle=pDevice->bHandle; + ioreq.irLength=0; + + outRec.status =flDefragmentVolume (&ioreq); + + outRec.data=ioreq.irLength; + if(copy_to_user(ioctlRecord.outputRecord,&outRec,sizeof(flOutputLnxRecord))) + return -EFAULT; + return 0; + } +#endif /* TFFS_DEBUG_DRIVER */ + + case 5: /* ATA pass-through command */ + return ata_passthrough (pDevice, &ioctlRecord, &inRec); + } + } + + + default: + PrintkDebug("TffsIoctl: no Tffs ioctl"); + return -EINVAL; + } + + /* do not check error code - it sended by outRec->status */ + flIOctl (&ioreq); + + return 0; +#else /* FL_IOCTL_INTERFACE */ + return 1; +#endif /* FL_IOCTL_INTERFACE */ +} + + + + +/******************************************************************************* + * * + * T f f s E n a b l e I R Q * + * * + * This routine enables DiskOnChip interrupt generation upon completion of * + * flash erase/write operation. Works with all types of DiskOnChip devices. * + * * + * Parameters: * + * * + * psoc socket pointer * + * * + * Returns: * + * * + * always zero (success) * + * * + *******************************************************************************/ + +int TffsEnableIRQ (SocketInfo * psoc) +{ + IOreq ioreq; + + ioreq.irHandle = psoc->bHandle; + ioreq.irFlags = FL_IRQ_RB_TYPE; + ioreq.irLength = (FL_INT_RB_ENABLED | /* FL_IRQ_EDGE_TYPE */ FL_IRQ_LEVEL_TYPE); + + flHwConfig (&ioreq); + + return 0; +} + + + + +/******************************************************************************* + * * + * T f f s S e t P I O * + * * + * If requested, this routine sets multi-sector polled I/O mode in DiskOnChip * + * H3 devices. It has no effect on H1/G4/G3 DiskOnChip devices. * + * * + * Parameters: * + * * + * psoc socket pointer * + * * + * Returns: * + * * + * zero if success otherwise respective error code * + * * + *******************************************************************************/ + +int TffsSetPIO (SocketInfo * psoc) +{ + IOreq ioreq; + DOCH_Error rc = DOCH_OK; + + if (tffs_pio > 0) /* multi-sector polled I/O mode requested */ + { + /* If we are going to use intermediate DMA buffer (which is one MMU page + * in size), we must make sure that multi-sector PIO won't overrun it. + */ + if( (tffs_dma_mode > 0) && !(tffs_dma_mode & 0x4) && + ((tffs_pio * FL_SECTOR_SIZE) > PAGE_SIZE) ) + { + PrintkError ("Multi-sector polled I/O overruns DMA buffer, disabled"); + tffs_pio = 0; + return -1; + } + + /* Set multi-sector polled I/O mode to transfer up to + * 'tffs_pio_mode' (but no more then 256) sectors at once. + */ + ioreq.irHandle = psoc->bHandle; + ioreq.irCount = DOCH_DATA_XFER_MODE_MULT; + ioreq.irLength = ((tffs_pio <= 255) ? tffs_pio : 0); + + if ((rc = flDOCHSetDataTransferMode(&ioreq)) != DOCH_OK) + { + PrintkError ("Can't set multi-sector polled I/O, error %d", rc); + tffs_pio = 0; + return -1; + } + PrintkInfo ("use multi-sector I/O (%d sectors)", tffs_pio); + } + else /* single-sector polled I/O mode requested */ + { + /* DiskOnChip H3 devices default to single-sector polled I/O mode + * upon reset, so we don't have to do anything here. + */ + } + + return (int)rc; +} + + + +/******************************************************************************* + * * + * T f f s S u s p e n d * + * * + * Power down DiskOnChip socket. * + * * + * Parameters: * + * * + * psoc socket pointer * + * * + * Returns: * + * * + * always zero (success) * + * * + *******************************************************************************/ + +int TffsSuspend (SocketInfo * psoc) +{ + IOreq ioreq; + + ioreq.irHandle = psoc->bHandle; + ioreq.irFlags = DEEP_POWER_DOWN; + + flDeepPowerDownMode (&ioreq); + + return 0; +} + + + + +/******************************************************************************* + * * + * T f f s R e s u m e * + * * + * Power up (previously powered down) DiskOnChip socket. * + * * + * Parameters: * + * * + * psoc socket pointer * + * * + * Returns: * + * * + * always zero (success) * + * * + *******************************************************************************/ + +int TffsResume (SocketInfo * psoc) +{ + IOreq ioreq; + + ioreq.irHandle = psoc->bHandle; + ioreq.irFlags = EXIT_DEEP_POWER_DOWN; + + flDeepPowerDownMode (&ioreq); + + return 0; +} + + + +static +void set_disk_geometry (DeviceInfo *pDisk) +{ + /* Limitations for old BIOSes: + no. of heads : 8 bits - max 255 + no. of cylinders: 10 bits - max 1023 + no. of sectors per track: 6 bits - max 63 */ + + if (pDisk->dwSize == 0) + { + pDisk->wCyl = 1; + pDisk->bHead = 1; + pDisk->bSect = 1; + return; + } + else if (pDisk->dwSize <= 0x800000) /* up to 4 GByte */ + { + unsigned long sectors, rest, minSec, maxSec, sec, minCyl, cyl; + + rest=sectors = (pDisk->dwSize >> pDisk->wTffsHWSectorSizeShift); /* use shared sector size instead kernel HW sector size - the same geometry for any harsect */ + + minSec=sectors/(1023*255); + if(sectors!=minSec*1023*255) + minSec++; + maxSec=63>>pDisk->wTffsHWSectorSizeShift; + minCyl=sectors/(maxSec*255); + if(sectors!=minCyl*maxSec*255) + minCyl++; + + for(sec=maxSec;sec>=minSec;sec--) + { + unsigned long minHead,maxHead,dwHead; + minHead=sectors/(sec*1023); + if(sectors!=minHead*sec*1023) + minHead++; + /* if(minHead%16) minHead=((minHead>>4)+1)<<4; */ + + maxHead=sectors/(sec*minCyl); + if(maxHead>255) + maxHead=255; + for(dwHead=minHead;dwHead<=maxHead;dwHead++ /*=16*/ ) + { + unsigned long tmp; + cyl=sectors/(sec*dwHead); + tmp=sectors-cyl*sec*dwHead; + if(rest>tmp) + { + pDisk->wCyl=cyl; + pDisk->bHead=dwHead; + pDisk->bSect=sec<wTffsHWSectorSizeShift; + if(tmp==0) + { + PrintkDebug("C/H/S (0) %u %u %u",pDisk->wCyl,pDisk->bHead,pDisk->bSect); + return; + } + rest=tmp; + } + } + } + } + else /* 4 .. 512 GByte */ + { + unsigned long heads = 16L, sectors_per_track = 63L, cylinders; + + /* Our preferences are (from highest to lowest): + * - 63 sectors per track + * - 16 heads + * - less then 65535 cylinders + */ + while ((cylinders = pDisk->dwSize / (heads * sectors_per_track)) > 65535L) + { + if (heads < 255L) heads++; + else if (sectors_per_track < 255L) sectors_per_track++; + else + { + PrintkError ("Error calculating C/H/S"); + break; + } + } + + pDisk->wCyl = (unsigned short) cylinders; + pDisk->bHead = (unsigned char) heads; + pDisk->bSect = (unsigned char) sectors_per_track; + + /* disk should have whole number of cylinders */ + pDisk->dwSize = (unsigned long)pDisk->wCyl * pDisk->bHead * pDisk->bSect; + } +} + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/tffs2lnx.h linux-2.6.30.4/drivers/block/tffs/tffs2lnx.h --- linux-2.6.30.4-orig/drivers/block/tffs/tffs2lnx.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/tffs2lnx.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,59 @@ +/****************************************************************************** + * * + * Project: DOC Driver for Linux 2.6 Block device driver for mDOC H3 family * + * of devices under Linux kernel 2.6. * + * * + * Version: 1.0 * + * Email questions to: oemsupport@sandisk.com * + * Copyright (C) SanDisk IL Ltd. 1995 - 2007 * + * SanDisk IL Ltd., 7 Atir Yeda Street, Kfar Saba 44425, Israel * + * * + ****************************************************************************** + * * + * 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 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, which is set forth in the readme.txt file. * + * 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., 51 * + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + * * + * This License does not grant you any right to use the trademarks, service * + * marks or logos of SanDisk IL Ltd. or SanDisk Corporation. * + * Subject to the foregoing, SanDisk IL Ltd., for itself and on behalf of its * + * licensors, hereby reserves all intellectual property rights in the program,* + * except for the rights expressly granted in this License. * + * * + ******************************************************************************/ + +/* + * $Log$ + */ + +#ifndef ___TFFS2LNX__H__ +#define ___TFFS2LNX__H__ + +/* Driver Functions */ +int TffsInit (void); +int TffsCleanup (void); +unsigned char TffsOpenDevice(DeviceInfo*pDevice); +unsigned char TffsCloseDevice(DeviceInfo*pDevice); +unsigned char TffsRead(DeviceInfo*pDevice,void*data,int block,int count); +unsigned char TffsWrite(DeviceInfo*pDevice,void*data,int block,int count); +int TffsIoctl(DeviceInfo*pDevice,int cmd,unsigned long arg); +unsigned char TffsIsWriteProtected(DeviceInfo*pDevice); + +/* enable DiskOnChip interrupt */ +extern int TffsEnableIRQ (SocketInfo *psoc); + +/* set multi-sector polled I/O mode */ +extern int TffsSetPIO (SocketInfo *psoc); + +/* suspend/resume power */ +extern int TffsSuspend (SocketInfo *psoc); +extern int TffsResume (SocketInfo *psoc); + +#endif /* ___TFFS2LNX__H__ */ diff -urN linux-2.6.30.4-orig/drivers/block/tffs/tffs_api.c linux-2.6.30.4/drivers/block/tffs/tffs_api.c --- linux-2.6.30.4-orig/drivers/block/tffs/tffs_api.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/tffs_api.c 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,5372 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Test for 7.x/src/H3/tffs_api.c-arc $ + * + * Rev 1.105 Feb 03 2008 12:21:18 Yuli.Izrailov + * Bug fix: bdCallTFFSToDOCH() - disk user attributes were retrieved on recover from power loss. + * Bug fix: memset was used instead of tffsset. + * + * Rev 1.100 Dec 25 2007 11:21:16 einat.avidan + * bug fix: unformat should not delete all partitions only if + * identified protected partitions + * + * Rev 1.99 Dec 16 2007 11:43:34 einat.avidan + * Add format start and format complete signatures in disk user attributes + * AbsMount: check format complete signature if format start signature exist + * + * + * Rev 1.98 Dec 04 2007 17:48:08 einat.avidan + * Bug fix: add check for format completeness in flAbsMountVolume + * Round requested fast area size up to unit Size + * Changed parameters passed to flDOCHWipeSectors + * Bug fix: TFFSChangeProtectionType failed setting partition as OTW + * + * Rev 1.97 Nov 04 2007 17:08:24 einat.avidan + * use secure erase command + * fix printout + * + * Rev 1.96 Oct 30 2007 17:12:00 einat.avidan + * new fast area type - FL_LENGTH_ALL + * unformat - delete partitions even if bad format + * implement eraseBD and SecureDelete by writing + * + * Rev 1.95 Oct 23 2007 11:30:36 einat.avidan + * update function documentation + * + * Rev 1.94 Oct 22 2007 11:34:56 einat.avidan + * update copyrights header + * + * Rev 1.93 Oct 11 2007 18:50:44 Einat.Avidan + * Replace global Boolean pattern with pattern in size of + * byte instead of dWord + * add compilation flags for SOTP and SLPP + * remove internal call to flDOCHFreeSectors in TFFSAbsDelete + * bug fix: TFFSWriteIPL did not support FL_IPL_SWAP_BYTES_MODE + * + * Rev 1.92 Sep 04 2007 15:42:24 einat.avidan + * bug fix: SCR 2993: flIdentifyProtection() does not report LOCK_ASSERTED + * + * Rev 1.91 Jul 02 2007 11:44:42 einat.avidan + * bug fix: SCR2966 : removed flags which are not in use + * FL_PREPARE_FOR_RESUME + * FL_IPL_NO_ADDRESS_SHIFT_MODE + * + * Rev 1.90 Jul 01 2007 13:47:28 einat.avidan + * bug fix: SCR 2964 compilation flag FL_VERIFY_WRITE should exclude \ include code for write verification + * + * Rev 1.89 Jun 20 2007 12:08:40 einat.avidan + * when DOCH_AUTO_DPD_BY_HOST is enabeled: wrong macro name was used(TFFS_API_IS_DPD_ON instead of TFFS_API_IS_AUTO_DPD_ON) + * + * Rev 1.88 Mar 22 2007 17:12:12 einat.avidan + * add SOTP + * + * Rev 1.87 Mar 22 2007 16:44:50 einat.avidan + * bug fix: TFFSVolumeInfo will return SLPP protection indication in case of SLPP and 0 otherwise. + * + * Rev 1.86 Mar 13 2007 13:47:18 einat.avidan + * add support for SLPP + * + * Rev 1.85 Mar 11 2007 16:59:06 einat.avidan + * bug fix: scr2886 flHardwareProtectionLock was not supported. + * bug fix: scr2819 maximum number of authentication tries of IPL partition was 1 + * + * Rev 1.84 Feb 28 2007 10:34:08 einat.avidan + * In write IPL – do not write whole partition, in order to reduce the time between reset and busy + * + * Rev 1.83 Feb 15 2007 17:53:14 Einat.Avidan + * Enable burst without DMA + * + * Rev 1.81.1.8 Nov 30 2006 10:24:16 Yaniv.Iarovici + * Fixed compilation warnings. + * + * Rev 1.81.1.7 Nov 21 2006 14:26:32 Yaniv.Iarovici + * Enable removing 'lock enabled' attribute from a partition. + * + * Rev 1.81.1.6 Nov 12 2006 09:48:00 Yaniv.Iarovici + * Write default/customized delay cell configuration values in flWriteIPL(). + * + * Rev 1.81.1.5 Nov 01 2006 08:56:28 Yaniv.Iarovici + * Prevent leaving ALL existing partitions in flFlashFormat(). + * + * Rev 1.81.1.4 Oct 31 2006 14:00:52 yaniv.iarovici + * Prevent setting a NON-CHANGABLE partition to CHANGEABLE. + * + * Rev 1.81.1.3 Oct 30 2006 15:50:40 yaniv.iarovici + * Fixed comment for flFlashFormat(). + * + * Rev 1.81.1.2 Oct 29 2006 11:00:00 Yaniv.Iarovici + * 1. All HW protection related routines enabled in bdCall() + * (Removed '#ifdef HW_PROTECTION') + * 2. Added casting to (void*) on 'DEFAULT_KEY' when calling tffsAPISetIoreq(). + * + * Rev 1.81.1.1 Oct 25 2006 09:10:48 Yaniv.Iarovici + * 1. Declare TFFSIdentifyProtection(). + * 2. Remove '#ifdef FL_EXTENDED_DISK_INFO' from implementation of TFFSGetExtendedDiskInfo(). + * 3. Change comment in description of TFFSFlashFormat(). + * 4. In TFFSUnFormat() - Check that all partitions are authenticated before trying to unformat. + * 5. Remove '#ifdef HW_PROTECTION' from implementation of protection routines. + * 6. Allow setting Normal IPL mode when using 8KB window. + * 7. Allow removing the 'CHANGEABLE_PROTECTION' attribute from a partition. + * + * Rev 1.81.1.0 Oct 22 2006 14:54:14 yaniv.iarovici + * 1. Fixed compilation warnings. + * 2. Changed flRegisterDOCH3SOC()return type to FLStatus. + * + * Rev 1.81 Oct 09 2006 14:06:06 yaniv.iarovici + * 1. Fixed compilation errors when FL_RDA_ONLY is defined + * 2. Fix TrueFFS version in TFFSGetExtendedDiskInfo() + * + * Rev 1.80 Oct 05 2006 11:01:22 yaniv.iarovici + * 1. Modified debug prints. + * 2. Removed unnecessary use of #ifdef HW_OTP + * 3. Fixed wrong protection attribute returned by TFFSIdentifyProtection() + * for READ and WRITE protected partition. + * + * Rev 1.79 Sep 14 2006 09:56:50 yaniv.iarovici + * Set IPL partition as 'protectable' upon its creation. + * + * Rev 1.78 Sep 13 2006 10:30:46 yaniv.iarovici + * Fix compilation warnings + * + * Rev 1.77 Sep 11 2006 13:45:28 yaniv.iarovici + * Legal header added + * + * Rev 1.76 Sep 03 2006 14:45:22 Yaniv.Iarovici + * 1. Allow calling TFFSGetExtendedDiskInfo() without request for specific partition info. + * 2. Bug fix: In TFFSChangeProtectionType() - set dwLockControl correctly. + * + * Rev 1.75 Aug 24 2006 11:40:04 Yaniv.Iarovici + * Bug fix in TFFSGetExtendedDiskInfo() - wrong return code checked. + * + * Rev 1.74 Aug 22 2006 13:26:56 Yaniv.Iarovici + * Fix calculation of 'numOfBinaryParToLeave' when BDK_ACCESS is defined. + * + * Rev 1.73 Aug 17 2006 15:33:28 Yaniv.Iarovici + * Remove Joint Protection + * + * Rev 1.71 Aug 17 2006 15:20:18 Yaniv.Iarovici + * 1) Encapsulate Joint Protection code under '#ifdef FL_JOINT_PROTECTION' (NOT define by default!) + * 2) Fix Joint protection support for Read protected partitions. + * + * Rev 1.69 Aug 16 2006 08:48:26 Yaniv.Iarovici + * 1) Enable READ+Write protection: + * - tffsFormatSetProtectionAttribs() + * - TFFSChangeProtectionType() + * 2) TFFSflashFormat(): + * - Add /LEAVE support for BDTL partitions as well as BDK + * - Rename 'binParToLeave; to 'numOfParToLeave ' + * - Encasulate BDK related code by '#ifdef BDK_ACCESS' + * 3) Fix description for TFFSChangeProtectionType() + * 4) Encapsulate BDK related code under '#ifdef BDK_ACCESS'. + * 5) Change error code returned by 'TFFSChangeProtectionKey()' to flHWProtection. + * + * Rev 1.67 Aug 09 2006 17:27:40 Polina.Marimont + * initial for DOC Driver 1.0 + * + * Rev 1.66 Aug 09 2006 17:20:28 Polina.Marimont + * initial for DOC Driver 1.0, DPD fixes from branch 1.64... applied + * + * Rev 1.63 Jul 03 2006 22:13:56 polina.marimont + * 1. bug fix - protection with leave failed to format + * 2. bug fix - flags returned by identifyProtection on OTW protected partition + * + * Rev 1.62 Jun 28 2006 11:34:56 Polina.Marimont + * bug fix - TFFSGetUniqueID() shoudl be enabled / disabled by HW_OTP flag and not by FL_EXTENDED_DISK_INFO + * + * Rev 1.61 Jun 28 2006 10:36:00 Polina.Marimont + * bug fix - writeIPL() on non-first data chunk caused to wrong data to be written + * + * Rev 1.60 Jun 27 2006 15:53:26 Polina.Marimont + * bug fix flVolumeInfo() API return base address + * + * Rev 1.59 Jun 26 2006 11:05:22 Polina.Marimont + * added include to hib.h file + * + * Rev 1.58 Jun 22 2006 17:55:38 Polina.Marimont + * compilation warnings fixes + * + * Rev 1.57 Jun 22 2006 13:18:40 Polina.Marimont + * updated comments + * + * Rev 1.56 Jun 22 2006 09:36:46 Polina.Marimont + * error codes compatibility for extendedDiskInfo() + * + * Rev 1.55 Jun 22 2006 09:06:06 Polina.Marimont + * TFFSRemoveProtectionKey() error code compatibily fix + * + * Rev 1.54 Jun 21 2006 18:25:42 Polina.Marimont + * 1. enter/exit DPD function fix + * 2. change protection to OTW updated + * 3. identify prrotection updated + * + * Rev 1.53 Jun 20 2006 12:40:28 Polina.Marimont + * error codes for insert key and authenticate partition fixed to be compatible to non mDOC h3 devices + * + * Rev 1.52 Jun 18 2006 13:09:00 Polina.Marimont + * 1. error codes changed to be compatible to non mDOC H3 devices + * 2. macros definition usage update + * 3. AutoDPD and DPD parameters set changed, storage moved to SA SDK + * + * Rev 1.51 Jun 14 2006 17:59:48 Polina.Marimont + * 1. structure definitions moved to header file + * 2. special function added for set IOreq structure parameters + * 3. printing fixes + * 4. bug fix - flash lifetime indication fix + * 5. bug fix - number of volume on unformatted device (returns 1) + * 6. check BDTL size should not be equal to 0, while formatting + * 7. unformat - remove all, including OTP and IPL partitions from the device + * 8. wipe sectors usage restored + * 9. bdkWriteInit() added check for requested size exceeded subpartition size + * 10. bug fix - used unit on BDK subparition rounded to the low boundary + * 11. When EDGE interrupt configured - print warning and configure to LEVEL interrupt. + * + * Rev 1.50 May 31 2006 15:41:44 polina.marimont + * TrueFFS 7.1.0 EQA16 + * + * Rev 1.49 May 28 2006 14:50:30 polina.marimont + * fix for IDENTIFY DEVICE + * + * Rev 1.48 May 28 2006 13:03:10 polina.marimont + * update for IDENTIFY DEVICE change + * + * Rev 1.47 May 24 2006 14:57:26 polina.marimont + * bugfix - erase BDK subpartition always erases first unit of subpartition 0 + * + * Rev 1.46 May 24 2006 08:17:06 polina.marimont + * dochVol.intermediateBuf - free added to tffsApiExit() function + * + * Rev 1.45 May 24 2006 08:13:30 polina.marimont + * TFFSbdkPartitionInfo() - wrong handle received from ioreq. + * + * Rev 1.44 May 21 2006 18:06:44 polina.marimont + * compilation errors fix, when CHECK_BEFORE_EVERY_COMMAND defined + * + * Rev 1.43 May 18 2006 14:29:56 polina.marimont + * TFFSBdkPartitionInfo() fixed to return flBadDriveHandle, when wrong number of partition specified, using migration variable + * + * Rev 1.42 May 18 2006 09:47:06 polina.marimont + * 1. IOCTL fixed + * 2. used size set back to 0 + * + * Rev 1.41 May 17 2006 15:42:28 polina.marimont + * 1. Error codes are fixed up to Legacy + SA package + * 2. LOCK and CHANGABLE protection support + * 3. Format fixed - common functions used to add IPL and OTP partitions, also to set partition protection attributes + * 4. PassThrough implemented + * 5. bug fixes + * + * Rev 1.40 Apr 11 2006 13:21:34 tal.heller + * enable EraseBD API. + * Bug Fix - Last Partition size wasn't initialized. + * Fix CC compilation + * adapt SecureDelete ioreq implementation to DOCH + * Bug Fix - StickLock API + * Comments syntax errors. + * + * Rev 1.39 Mar 29 2006 16:39:50 DoronC + * Bug fix - compilation warnings ove various compilers. + * + * Rev 1.38 Mar 27 2006 16:21:58 DoronC + * Add DMA support. + * + * Rev 1.37 Mar 22 2006 17:35:46 DoronC + * Bug fix - add signature to disk attributes in order to use only + * format made by TrueFFS 7.1 and not by host SDK. + * Other format will force reformatting of the media. + * + * Rev 1.36 Mar 20 2006 17:21:58 DoronC + * Bug fix - read IPL using buffers failed. + * + * Rev 1.35 Mar 20 2006 10:41:16 DoronC + * Bug fix - protection change was not working. + * + * Rev 1.34 Mar 15 2006 16:17:54 DoronC + * Bug fix - wrong flag was checked when reading IPL. + * + * Rev 1.33 Mar 15 2006 15:58:04 DoronC + * Bug fix - change protection key caused an exception. + * + * Rev 1.32 Mar 15 2006 14:14:46 DoronC + * Bug fix - formating protected partition with no active protection failed. + * Bug fix - IPL flags were not checked. + * + * Rev 1.31 Mar 15 2006 11:28:16 DoronC + * Bug fix - IPL write was not working properly. + * Bug fix - BDK used size was faulty. + * + * Rev 1.30 Mar 14 2006 09:53:52 DoronC + * Bug fix - DOCFlash win field was not initialized by the init routine + * causing exception on some conditions. + * + * Rev 1.29 Mar 06 2006 08:40:52 DoronC + * Bug fix - protection identify was reported wrong. + * + * Rev 1.28 Mar 05 2006 15:52:24 DoronC + * Protection structure of H3 changed to contain dwords instead + * of words. + * + * Rev 1.27 Mar 02 2006 12:02:30 DoronC + * Bug fix - mount was checked for wrong number of partitions. + * + * Rev 1.26 Mar 02 2006 08:30:26 DoronC + * Host SDK API changed from IOreq2 to IOreq. + * + * Rev 1.25 Feb 16 2006 11:32:38 DoronC + * Store binary partition flags in the attributes and return then + * when requested by extendedInfo for computability with legacy + * devices. + * + * Rev 1.24 Feb 16 2006 10:02:40 DoronC + * Bug fix - Compilation warnings removed. + * Bug fix - Combining DPS between BDK and BDTL was not + * working properly during format. + * Bug fix - change protection key&type of combined DPS was not + * working. + * + * Rev 1.23 Feb 14 2006 10:50:02 DoronC + * Remove large variables from stack. use one global buffer for + * all large buffers needs. + */ + + +#include "flsystem.h" +#include "flcustom.h" +#include "defs.h" +#include "flbase.h" +#include "flstdcmp.h" + +#include "flsystyp.h" +#include "flchkdef.h" +#include "blockdev.h" +#include "_docsys.h" + +#include "hib.h" +#include "doch_ata.h" +#include "doch_api.h" +#include "bdkemul.h" +#include "tffs_api.h" +#include "doch_func.h" +#include "dochtl.h" + + +#define MAX_MOUNT_COUNT 100 /*100 Times...*/ +#define DOCH_NUM_OF_PLANES 1 +#define DOCH_NUM_OF_BANKS 1 +#define DOCH_SECTORS_PER_PAGE 4 +#define DOCH_SHARED_SECTORS 32 + +#define DOCH_CAPACITY_128MB 0x40000 /*In Sectors*/ +#define DOCH_CAPACITY_256MB 0x80000 /*In Sectors*/ +#define DOCH_CAPACITY_512MB 0x100000 /*In Sectors*/ +#define DOCH_CAPACITY_1GB 0x200000 /*In Sectors*/ +#define DOCH_CAPACITY_2GB 0x400000 /*In Sectors*/ +#define DOCH_CAPACITY_4GB 0x800000 /*In Sectors*/ +#define DOCH_CAPACITY_8GB 0x1000000 /*In Sectors*/ + +#define DOCH_UNIT_SIZE_256KB 0x40000 /*In Bytes*/ +#define DOCH_UNIT_SIZE_512KB 0x80000 /*In Bytes*/ +#define DOCH_UNIT_SIZE_1MB 0x100000 /*In Bytes*/ +#define DOCH_UNIT_SIZE_2MB 0x200000 /*In Bytes*/ +#define DOCH_UNIT_SIZE_4MB 0x400000 /*In Bytes*/ + +#define createIrHandle(socket, partition) ((socket) + ((partition) << 4)); + +/********************/ +/* Externs */ +/********************/ + +#ifdef __cplusplus +extern "C" { +#endif + +extern FLByte gIsDMAEnabled; /*DMA is Enabled/Disabled*/ +extern DOCH_DpdSettings gDpdSettings; + +#ifdef CHECK_POWER_ON_EVERY_COMMAND +extern FLByte gDeviceTurnedOff; +#endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + +#ifdef __cplusplus +} +#endif + +/********************/ +/* Global Vars */ +/********************/ + +DocHVolume dochVol; +FLBoolean dochBdCallWasCalled = FALSE; +FLBoolean dochGotDiskUserAttributes = FALSE; + +#ifdef CHECK_POWER_ON_EVERY_COMMAND +#define TFFS_API_RET(rc)((rc==DOCH_DeviceTurnedOff) ? flSuspendModeDetected : flGeneralFailure) +#else /*CHECK_POWER_ON_EVERY_COMMAND*/ +#define TFFS_API_RET(rc) flGeneralFailure +#endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + +#define TFFS_API_GET_UNIT_SIZE(myIoreq, ioreq, dochStatus, flStatus){\ + DOCH_DeviceInfo * pDevInfo = (DOCH_DeviceInfo*)dochVol.intermediateBuf;\ + dochStatus = flDOCHIdentifyDiskOnChipDevice(tffsAPISetIoreq(&myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq), 0,0,dochVol.intermediateBuf, 0,0));\ + if(dochStatus != DOCH_OK){\ + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("flDOCHIdentifyDiskOnChipDevice failed with status: 0x%x "),dochStatus));\ + return (dochStatus==DOCH_DiskNotFound)? flUnknownMedia:TFFS_API_RET(dochStatus);}\ + dochVol.dwUnformattedCapacity = pDevInfo->dwUnformattedCapacity;\ + dochVol.dwVirtualUnitSizeInSectors = (pDevInfo->dwUnitSize!=0) ? pDevInfo->dwUnitSize : (dochVol.dwUnformattedCapacity>>9);\ + dochVol.dwVirtualUnitSize = ((dochVol.dwVirtualUnitSizeInSectors)<dwOtpEnabled = ((protectionType & CHANGEABLE_PROTECTION) && \ + (!(protectionType & SECTOR_LEVEL_PROTECTION))) ? TRUE : FALSE;\ + pPartitionFormatInfoAPI->dwPartitionType = DOCH_PRT_TYPE_NORMAL;\ + pPartitionFormatInfoAPI->dwPerformanceControl = DOCH_NORMAL_PERFORMANCE;\ + pPartitionFormatInfoAPI->dwPageSizeExp = DOCH_PAGE_SIZE_512B;\ + pPartitionFormatInfoAPI->dwHashType = DOCH_HASH_TYPE_SHA1;\ + pPartitionFormatInfoAPI->dwEncryptionType = DOCH_ENCRYPT_NONE;\ + pPartitionFormatInfoAPI->dwMasterControl = DOCH_PART_ACCESS_MODE_FULL;\ + pPartitionFormatInfoAPI->dwMaxNumOfAuthAttempts = DOCH_MAX_PWD_ATTEMPTS;\ + pPartitionFormatInfoAPI->bSOTP = FALSE; +#else /*FL_SLPP*/ + /*SOTP is supported and SLPP isn't*/ + #define TFFS_API_SET_MIG_STD_PART_PRMS(pPartitionFormatInfoAPI, protectionType)\ + pPartitionFormatInfoAPI->dwOtpEnabled = (protectionType & CHANGEABLE_PROTECTION) ? TRUE : FALSE;\ + pPartitionFormatInfoAPI->dwPartitionType = DOCH_PRT_TYPE_NORMAL;\ + pPartitionFormatInfoAPI->dwPerformanceControl = DOCH_NORMAL_PERFORMANCE;\ + pPartitionFormatInfoAPI->dwPageSizeExp = DOCH_PAGE_SIZE_512B;\ + pPartitionFormatInfoAPI->dwHashType = DOCH_HASH_TYPE_SHA1;\ + pPartitionFormatInfoAPI->dwEncryptionType = DOCH_ENCRYPT_NONE;\ + pPartitionFormatInfoAPI->dwMasterControl = DOCH_PART_ACCESS_MODE_FULL;\ + pPartitionFormatInfoAPI->dwMaxNumOfAuthAttempts = DOCH_MAX_PWD_ATTEMPTS;\ + pPartitionFormatInfoAPI->bSOTP = FALSE; +#endif /*FL_SLPP*/ +#else /*FL_SOTP*/ +#ifdef FL_SLPP + /*SOTP is not supported and SLPP is supported*/ + #define TFFS_API_SET_MIG_STD_PART_PRMS(pPartitionFormatInfoAPI, protectionType)\ + pPartitionFormatInfoAPI->dwOtpEnabled = ((protectionType & CHANGEABLE_PROTECTION) && \ + (!(protectionType & SECTOR_LEVEL_PROTECTION))) ? TRUE : FALSE;\ + pPartitionFormatInfoAPI->dwPartitionType = DOCH_PRT_TYPE_NORMAL;\ + pPartitionFormatInfoAPI->dwPerformanceControl = DOCH_NORMAL_PERFORMANCE;\ + pPartitionFormatInfoAPI->dwPageSizeExp = DOCH_PAGE_SIZE_512B;\ + pPartitionFormatInfoAPI->dwHashType = DOCH_HASH_TYPE_SHA1;\ + pPartitionFormatInfoAPI->dwEncryptionType = DOCH_ENCRYPT_NONE;\ + pPartitionFormatInfoAPI->dwMasterControl = DOCH_PART_ACCESS_MODE_FULL;\ + pPartitionFormatInfoAPI->dwMaxNumOfAuthAttempts = DOCH_MAX_PWD_ATTEMPTS; +#else /*FL_SLPP*/ + /*both SOTP and SLPP are not supported*/ + #define TFFS_API_SET_MIG_STD_PART_PRMS(pPartitionFormatInfoAPI, protectionType)\ + pPartitionFormatInfoAPI->dwOtpEnabled = (protectionType & CHANGEABLE_PROTECTION) ? TRUE : FALSE;\ + pPartitionFormatInfoAPI->dwPartitionType = DOCH_PRT_TYPE_NORMAL;\ + pPartitionFormatInfoAPI->dwPerformanceControl = DOCH_NORMAL_PERFORMANCE;\ + pPartitionFormatInfoAPI->dwPageSizeExp = DOCH_PAGE_SIZE_512B;\ + pPartitionFormatInfoAPI->dwHashType = DOCH_HASH_TYPE_SHA1;\ + pPartitionFormatInfoAPI->dwEncryptionType = DOCH_ENCRYPT_NONE;\ + pPartitionFormatInfoAPI->dwMasterControl = DOCH_PART_ACCESS_MODE_FULL;\ + pPartitionFormatInfoAPI->dwMaxNumOfAuthAttempts = DOCH_MAX_PWD_ATTEMPTS; +#endif /*FL_SLPP*/ +#endif /*FL_SOTP*/ +/*********************/ +/* Static functions */ +/*********************/ +#ifndef FL_READ_ONLY +static FLStatus tffsApiAddOtpIPL(FLBoolean bIPL, IOreq * myIoreq, IOreq * ioreq); +static FLStatus tffsFormatSetProtectionAttribs(FLByte bProtType, DOCH_PartitionFormatInfoAPI* pPartitionFormatInfoAPI, FLByte * bKey, FLWord wKeyLen); +#endif /*FL_READ_ONLY*/ + +static FLStatus tffsApiAuthPartition(IOreq * myIoreq, IOreq * ioreq, FLByte bPartNo, FLByte * pKey, FLWord wKeyLen); +static IOreq* tffsAPISetIoreq(IOreq * pIoreq, FLHandle irHandle, FLDword irFlags, void* irPath, void * irData, FLSDword irLength, FLSDword irCount); + +static FLStatus TFFSIdentifyProtection(IOreq* ioreq); + +/*----------------------------------------------------------------------*/ +/* Function name : actualPartitionNum*/ +/* Description : */ +/* Return type : FLStatus */ +/* Argument : FLByte* partNum*/ +/* Argument : FLByte partitionType*/ +/*----------------------------------------------------------------------*/ +FLStatus actualPartitionNum(FLByte* partNum, FLByte partitionType, FLSDword sdwSocketNo) +{ + DOCH_Socket* pDev; + + DOCH_get_socket(pDev, sdwSocketNo); + if( pDev==NULL ) + return flBadParameter; + + switch(partitionType) + { + case PARTITION_TYPE_IPL: + break; + + case PARTITION_TYPE_BDTL: + *partNum += (dochVol.numOfBinaryPartitions + (dochVol.iplExists + dochVol.otpExists)); + break; + + case PARTITION_TYPE_BINARY: +#ifdef BDK_ACCESS + *partNum += (dochVol.iplExists + dochVol.otpExists); + break; +#else /*BDK_ACCESS*/ + return flPartitionNotFound; +#endif /*BDK_ACCESS*/ + + case PARTITION_TYPE_OTP: + break; + + default: + break; + } + + if( (*partNum) == 0 ) + return flOK; + + if( ((*partNum) >= DOCH_MAX_PARTITIONS) || ((*partNum) >=pDev->wTotalNumOfPartitions) ) + return flPartitionNotFound; + + return flOK; +}/*actualPartitionNum()*/ + + +/*----------------------------------------------------------------------*/ +/* T F F S E x t e n d e d G e t D i s k I n f o */ +/* */ +/* Returns general information about the Device and a specific partition */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Must be set to 0 */ +/* bits 3-0 - Socket # (zero based) */ +/* irCount : Partition number */ +/* irFlags : Either FL_BDK_PARTITION or FL_DISK_PARTITION */ +/* irData : Address of FLExtendedDiskInfo structure */ +/* irLength : Floor number to access - FL_ALL_FLOORS */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSGetExtendedDiskInfo(IOreq* ioreq) +{ + DOCH_Error rc; + FLStatus flStatus = flOK; + DOCH_Error specificPartRC = DOCH_PartitionNotFound; + DOCH_Error iplRC = DOCH_PartitionNotFound; + IOreq myIoreq; + FLExtendedDiskInfo FAR1 * info = (FLExtendedDiskInfo FAR1 *)ioreq->irData; + FLDword dwIPLSize; + FLByte bNumOfBinaryPartitions, partition; + FLWord wTotalNumOfPartitions; + FLDword dwPartitionFlags = 0; + DOCH_DeviceInfo * pDochDevInfo = (DOCH_DeviceInfo*)dochVol.intermediateBuf; + DOCH_DiskUserAttrWithBinary * pDiskUserAttrWithBinary = (DOCH_DiskUserAttrWithBinary*)dochVol.intermediateBuf; + DOCH_PartitionUserAttrWithBinary* pPartUserAttrWithBinary = (DOCH_PartitionUserAttrWithBinary*)dochVol.intermediateBuf; + DOCH_Socket * pDev; + + DOCH_get_socket(pDev, FL_GET_SOCKET_FROM_HANDLE(ioreq)); + + + /*Retrieve DOCH extended info structure*/ + /*-------------------------------------*/ + rc = flDOCHIdentifyDiskOnChipDevice(tffsAPISetIoreq(&myIoreq,FL_GET_SOCKET_FROM_HANDLE(ioreq),0,0,dochVol.intermediateBuf,0,0)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSGetExtendedDiskInfo(): flDOCHIdentifyDiskOnChipDevice failed with status: %d "), rc)); + return (rc==DOCH_DiskNotFound)? flUnknownMedia:TFFS_API_RET(rc); + } + + TFFS_API_GET_UNIT_SIZE(myIoreq,ioreq, rc, flStatus); + + wTotalNumOfPartitions = pDochDevInfo->wTotalNumOfPartitions; + + /* Retrieve Disk User Attributes */ + /*-------------------------------*/ + rc = flDOCHGetDiskUserAttributes(tffsAPISetIoreq(&myIoreq,FL_GET_SOCKET_FROM_HANDLE(ioreq), 0,0,dochVol.intermediateBuf,0,0)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSGetExtendedDiskInfo(): flDOCHGetDiskUserAttributes failed with status: 0x%x "),rc)); + return (rc==DOCH_ProtectionFault)?flHWProtection:flBadFormat; /* if not protected -> like media header not found */ + } + + /* Check if device is not formatted */ + if( (! pDiskUserAttrWithBinary->bIplPresent) && (! pDiskUserAttrWithBinary->bOtpPresent) ) + { + /*Fill only relevant fields*/ + info->dwTLType = 0; + info->dwFormatFlags = 0; + info->dwTrueFFSVersion = 0; + info->dwFlashTechnology = 0; + info->dwType = FL_H3; + info->dwSubType = 0; + info->bMediaType = 0; + info->bNoOfFloors = (FLByte)pDev->wNumOfDevices; + info->bNoOfPlanes = DOCH_NUM_OF_PLANES; + info->bNoOfBanks = DOCH_NUM_OF_BANKS; + info->bDataBusWidth = 16; /*DOCH always uses 16bit*/ + info->bSectorsPerPage = DOCH_SECTORS_PER_PAGE; + info->bSharedSectors = DOCH_SHARED_SECTORS; + info->bFastAreaSharedSectors = 0; + info->bMaxRelatedSectors = 0; + info->dwIPLSize = 0; + info->bChangeableProtectedAreas = 0; + info->btotalProtectedAreas = 0; + info->dwUnitsInFirstFloor = 0; + info->dwUnitSize = dochVol.dwVirtualUnitSize; + info->dwMaxBadPercentage = 0; + + info->bNoOfBinaryPartitions = 0; + info->bNoOfDiskPartitions = 0; + info->bBlockMultiplierBits = 0; + info->dwPercentUsed = 0; + info->bHeaderUnits = 0; + info->wHeaderLocation = 0; + + /* Programmer name and version strings */ + /* Retrieve from disk attributes*/ + tffscpy(info->bProgrammerNamePtr, pDiskUserAttrWithBinary->bProgrammerName, sizeof(FLDword)); + tffscpy(info->bProgrammerVersionPtr, pDiskUserAttrWithBinary->bProgrammerVersion, sizeof(FLDword)); + info->dwTrueFFSVersion = 0; + DBG_PRINT_ERR(FLZONE_API, "TFFSGetExtendedDiskInfo(): device NOT formatted \r\n"); + return flBadFormat; + } + wTotalNumOfPartitions = wTotalNumOfPartitions - pDiskUserAttrWithBinary->bIplPresent - + pDiskUserAttrWithBinary->bOtpPresent; + bNumOfBinaryPartitions = pDiskUserAttrWithBinary->bNumOfBinaryPartitions; + + /* Programmer name and version strings */ + tffscpy(&info->bProgrammerNamePtr[0], pDiskUserAttrWithBinary->bProgrammerName, + sizeof(pDiskUserAttrWithBinary->bProgrammerName)); + tffscpy(&info->bProgrammerVersionPtr[0], pDiskUserAttrWithBinary->bProgrammerVersion, + sizeof(pDiskUserAttrWithBinary->bProgrammerVersion)); + + info->dwTrueFFSVersion = + (((pDiskUserAttrWithBinary->bTFFSVersion[0] - 0x30)*1000) + + ((pDiskUserAttrWithBinary->bTFFSVersion[1] - 0x30)*100 ) + + ((pDiskUserAttrWithBinary->bTFFSVersion[2] - 0x30)*10 ) + + (pDiskUserAttrWithBinary->bTFFSVersion[3] - 0x30)); + + /*Retrieve IPL partition size*/ + /*---------------------------*/ + iplRC = flDOCHPartitionInfo(tffsAPISetIoreq(&myIoreq,FL_GET_SOCKET_FROM_HANDLE(ioreq) + (DOCH_IPL_PARTITION_NUM << 4), + 0,0,dochVol.intermediateBuf,0,0)); + if(iplRC != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSGetExtendedDiskInfo(): flDOCHPartitionInfo of IPL partition failed with status: 0x%x "), rc)); + return (iplRC==DOCH_ProtectionFault)?flHWProtection:flBadFormat; /* if not protected, but fails -> like bad format */ + } + dwIPLSize = ((DOCH_PartitionInfo*)dochVol.intermediateBuf)->nPartitionSize << DOCH_SECTOR_SIZE_BITS; + + /* Fill FLExtendedDiskInfo structure */ + /*--------------------------------------*/ + + /******************************************/ + /* Fields that belong to the entire media */ + /******************************************/ + info->dwTLType = 0; + info->dwFormatFlags = 0; + + info->dwFlashTechnology = 0; + info->dwType = FL_H3; + info->dwSubType = 0; + info->bMediaType = 0; + info->bNoOfFloors = (FLByte)pDev->wNumOfDevices; + info->bNoOfPlanes = DOCH_NUM_OF_PLANES; + info->bNoOfBanks = DOCH_NUM_OF_BANKS; + info->bDataBusWidth = 16; /*DOCH always uses 16bit*/ + info->bSectorsPerPage = DOCH_SECTORS_PER_PAGE; + info->bSharedSectors = DOCH_SHARED_SECTORS; + info->bFastAreaSharedSectors = 0; + info->bMaxRelatedSectors = 0; + info->dwIPLSize = dwIPLSize; + info->bChangeableProtectedAreas = 2; + info->btotalProtectedAreas = 2; + info->dwUnitsInFirstFloor = 0; + info->dwUnitSize = dochVol.dwVirtualUnitSize; + info->dwMaxBadPercentage = 0; + + info->bNoOfBinaryPartitions = bNumOfBinaryPartitions; + info->bNoOfDiskPartitions = wTotalNumOfPartitions - bNumOfBinaryPartitions; + info->bBlockMultiplierBits = 0; + info->dwPercentUsed = 0; + info->bHeaderUnits = 0; + info->wHeaderLocation = 0; + + + /*Retrieve specific partition info + Note that the specific partition is always a BDTL partition + Hence jumping over IPL/OTP/Binary Partition + -------------------------------------------*/ + partition = (FLByte)ioreq->irCount; + if(partition != FL_EXT_INFO_NO_SPEC_PART) + { + if(ioreq->irFlags == FL_DISK_PARTITION) + flStatus = actualPartitionNum(&partition, PARTITION_TYPE_BDTL, FL_GET_SOCKET_FROM_HANDLE(ioreq)); + else if(ioreq->irFlags == FL_BDK_PARTITION) + { + #ifdef BDK_ACCESS + flStatus = actualPartitionNum(&partition, PARTITION_TYPE_BINARY, FL_GET_SOCKET_FROM_HANDLE(ioreq)); + #else /*BDK_ACCESS*/ + return flPartitionNotFound; + #endif /*BDK_ACCESS*/ + } + if( flStatus!=flOK ) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSGetExtendedDiskInfo(): specific partition NOT FOUND \r\n"); + return flStatus; + } + + specificPartRC = flDOCHGetParitionUserAttributes(tffsAPISetIoreq(&myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq) + (partition << 4), + 0,0,dochVol.intermediateBuf,0,0)); + if(specificPartRC != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSGetExtendedDiskInfo(): specific partition NOT FOUND \r\n"); + return (specificPartRC==DOCH_ProtectionFault)? flHWProtection : flBadDriveHandle; + } + if ((ioreq->irFlags == FL_DISK_PARTITION) && (pPartUserAttrWithBinary->bType != PARTITION_TYPE_BDTL)) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSGetExtendedDiskInfo(): Partition is not BDTL partition. \r\n"); + return flGeneralFailure; + } + + #ifdef BDK_ACCESS + if ((ioreq->irFlags == FL_BDK_PARTITION) && (pPartUserAttrWithBinary->bType != PARTITION_TYPE_BINARY)) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSGetExtendedDiskInfo(): Partition is not BDK partition. \r\n"); + return flGeneralFailure; + } + + if( pPartUserAttrWithBinary->bType == PARTITION_TYPE_BINARY ) + dwPartitionFlags = pPartUserAttrWithBinary->binPartHeader.dwPartitionFlags; + #endif /*BDK_ACCESS*/ + + specificPartRC = flDOCHPartitionInfo(tffsAPISetIoreq( &myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq) + (partition << 4), + 0, 0, dochVol.intermediateBuf, 0, 0)); + /* Check if partition exists */ + if(specificPartRC == DOCH_PartitionNotFound) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSGetExtendedDiskInfo(): specific partition NOT FOUND \r\n"); + return flBadDriveHandle; + } + /************************************************/ + /* Fields that belong to the specific partition */ + /************************************************/ + if(specificPartRC == DOCH_OK) + { + DOCH_PartitionInfo* pPartInfo = (DOCH_PartitionInfo*)dochVol.intermediateBuf; + info->wHeaderLocation = 0; + info->dwVirtualUnits = pPartInfo->nPartitionSize/dochVol.dwVirtualUnitSizeInSectors; + info->dwNormalAreaUnitSize = dochVol.dwVirtualUnitSize; + if(ioreq->irFlags == FL_DISK_PARTITION) + { + info->dwFastAreaVirtualFactor = pPartInfo->wFastAreaFactor; + info->dwFastAreaLogicalUnitSize = dochVol.dwVirtualUnitSize / (1<wFastAreaFactor); + info->dwFastUnits = pPartInfo->nFastAreaSize / (info->dwFastAreaLogicalUnitSize>>DOCH_SECTOR_SIZE_BITS); + } + else + {/* binary partition */ + #ifdef BDK_ACCESS + info->dwFastAreaVirtualFactor = 0; + info->dwFastAreaLogicalUnitSize = 0; + info->dwFastUnits = 0; + #else /*BDK_ACCESS*/ + return flPartitionNotFound; + #endif /*BDK_ACCESS*/ + } + info->dwFirstUnit = 0; + info->dwLastUnit = info->dwVirtualUnits; + info->dwPartitionFlags = dwPartitionFlags; + info->dwFirstQuickMountUnit = 0; + info->dwSpareUnits = 0; + info->dwTransferUnits = 0; + + + info->bMinSectorsForFolding = 0; + info->bMinSectorsForNextWrite = 0; + info->bfastAreaMinSectorsForNextWrite = 0; + + /******************************************/ + /* Fields that are valid only after mount */ + /******************************************/ + info->dwUsedUnits = 0; + info->dwFreeUnits = 0; + info->bNeededFreeUnits = 0; + info->dwUMDBBTSector = 0; + } + else + return TFFS_API_RET(specificPartRC); + + }/*end of if(partition != FL_EXT_INFO_NO_SPEC_PART)*/ + + return flOK; +}/*TFFSGetExtendedDiskInfo()*/ + + +/*----------------------------------------------------------------------*/ +/* T F F S V o l u m e I n f o */ +/* */ +/* Get general information about the media. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (0,1,..) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irData : Address of user buffer to read general */ +/* information into. */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/* irFlags : SECTOR_LEVEL_PROTECTION if the partition is */ +/* defined as SLPP */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSVolumeInfo(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq myIoreq; + VolumeInfoRecord FAR1 * volumeInfo = (VolumeInfoRecord FAR1 *)ioreq->irData; + FLDword dwPartitionSize; + + /*Retrieve specific partition info*/ + /*--------------------------------*/ + rc = flDOCHPartitionInfo(tffsAPISetIoreq(&myIoreq, ioreq->irHandle, 0,0,dochVol.intermediateBuf,0,0)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSVolumeInfo(): flDOCHPartitionInfo failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flBadDriveHandle : TFFS_API_RET(rc)); + } + dwPartitionSize = ((DOCH_PartitionInfo*)dochVol.intermediateBuf)->nPartitionSize; + +#ifdef FL_SLPP + /* Is the partition SLPP?*/ + if(((((DOCH_PartitionInfo*)dochVol.intermediateBuf)->partitionAttributes2 & DOCH_PA2B_PROTECTION_TYPE) >> DOCH_PA2O_PROTECTION_TYPE) + == DOCH_PARTITION_SLPP_PROTECTED) + ioreq->irFlags = SECTOR_LEVEL_PROTECTION; + else + ioreq->irFlags = 0; +#endif /*FL_SLPP*/ + + /*Retrieve DOCH extended info structure and calculate unit number if required */ + TFFS_API_GET_UNIT_SIZE(myIoreq, ioreq, rc, flStatus); + + /* Fill VolumeInfoRecord structure */ + /*----------------------------------*/ + /*Media Geometry*/ + flBuildGeometry( dwPartitionSize, &volumeInfo->cylinders, + &volumeInfo->heads, &volumeInfo->sectors, + FALSE, (FLWord)ioreq->irHandle); + + volumeInfo->logicalSectors = dwPartitionSize; + volumeInfo->bootAreaSize = 0; + /* Return window base reg */ + /*------------------------*/ + tffsAPISetIoreq( &myIoreq,FL_GET_SOCKET_FROM_HANDLE(ioreq),0,0,0,0,0); + rc=flDOCHGetPhysicalAddress(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSGetPhysicalInfo(): DOCHGetPhysicalAddress failed with status: 0x%x "), rc)); + return (DOCH_DiskNotFound==rc) ? flAdapterNotFound : TFFS_API_RET(rc); + } + volumeInfo->baseAddress = myIoreq.irCount; + +#ifdef FL_LOW_LEVEL + volumeInfo->flashType = FL_H3; + volumeInfo->dwPhysicalUnitSize = dochVol.dwVirtualUnitSizeInSectors; + volumeInfo->dwPhysicalSize = dochVol.dwUnformattedCapacity; + volumeInfo->DOCType = FL_H3; + volumeInfo->lifeTime= 1; /*1 - indicates fresh media*/ +#endif /*FL_LOW_LEVEL*/ + + tffsset(volumeInfo->driverVer,0,sizeof(volumeInfo->driverVer)); + tffscpy(volumeInfo->driverVer,driverVersion, + TFFSMIN(sizeof(volumeInfo->driverVer),sizeof(driverVersion))); + + tffsset(volumeInfo->OSAKVer,0,sizeof(volumeInfo->OSAKVer)); + tffscpy(volumeInfo->OSAKVer, OSAKVersion, + TFFSMIN(sizeof(volumeInfo->OSAKVer),sizeof(OSAKVersion))); + + return flOK; +}/*TFFSVolumeInfo()*/ + +/*----------------------------------------------------------------------*/ +/* T F F S C o u n t V o l u m e s */ +/* */ +/* Counts the number of volumes on the Flash device. */ +/* */ +/* Not all the volumes necessarily need to be mounted. A drive formated */ +/* with a read protection will be registered but can not be accessed. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* : Partition number ( 0,1,2... ) */ +/* */ +/* Returns: */ +/* irFlags : Number of partitions */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSCountVolumes(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_GeneralFailure; + + IOreq myIoreq; + FLByte bNumOfPartition; + DOCH_DiskUserAttrWithBinary * pDiskUserAttrWithBinary = (DOCH_DiskUserAttrWithBinary *)(dochVol.intermediateBuf); + + /*Retrieve DOCH global info structure*/ + /*-------------------------------------*/ + rc = flDOCHIdentifyDiskOnChipDevice(tffsAPISetIoreq(&myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq), + 0,0,dochVol.intermediateBuf, 0,0)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSCountVolumes(): flDOCHIdentifyDiskOnChipDevice failed with status: 0x%x "), rc)); + return (rc==DOCH_DiskNotFound)? flUnknownMedia : TFFS_API_RET(rc); + } + bNumOfPartition = (FLByte)((DOCH_DeviceInfo*)dochVol.intermediateBuf)->wTotalNumOfPartitions; + + /*Retrieve disk attributes*/ + rc = flDOCHGetDiskUserAttributes(tffsAPISetIoreq( &myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq), 0,0, + dochVol.intermediateBuf,0,0)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSCountVolumes(): flDOCHGetDiskUserAttributes failed with status: 0x%x"), rc)); + return (rc==DOCH_ProtectionFault)?flHWProtection:TFFS_API_RET(rc); + } + bNumOfPartition = bNumOfPartition - pDiskUserAttrWithBinary->bIplPresent - + pDiskUserAttrWithBinary->bOtpPresent - pDiskUserAttrWithBinary->bNumOfBinaryPartitions; + + /*Extract # of partitions from Extended Info*/ + /*------------------------------------------*/ + ioreq->irFlags = bNumOfPartition; + + /* fix number of partitions - unformatted device should return 1*/ + if( (pDiskUserAttrWithBinary->bNumOfBinaryPartitions==0) && + (bNumOfPartition==0) ) + { + ioreq->irFlags = 1; + } + return flOK; +}/* TFFSCountVolumes() */ + + +/*----------------------------------------------------------------------*/ +/* f l S e c t o r s I n V o l u m e */ +/* */ +/* Returns number of virtual sectors in volume. */ +/* */ +/* In case the inserted volume is not mounted, returns current status. */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/* irLength : number of virtual sectors in volume */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSSectorsInVolume(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq myIoreq; + + + /*Retrieve specific partition info*/ + /*--------------------------------*/ + myIoreq.irHandle = ioreq->irHandle; + myIoreq.irData = dochVol.intermediateBuf; + + rc = flDOCHPartitionInfo(tffsAPISetIoreq(&myIoreq, ioreq->irHandle, 0,0,dochVol.intermediateBuf,0,0)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSSectorsInVolume(): flDOCHPartitionInfo failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flBadDriveHandle : TFFS_API_RET(rc)); + } + + ioreq->irLength = ((DOCH_PartitionInfo*)dochVol.intermediateBuf)->nPartitionSize; + return flOK; +}/* TFFSSectorsInVolume */ + +#ifndef FL_NO_QUICK_MOUNT_FEATURE +/*----------------------------------------------------------------------*/ +/* */ +/* Quick mount routines are Obsoleted for DOCH */ +/* */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSClearQuickMountInfo(IOreq* ioreq) +{ + return flOK; +}/*TFFSClearQuickMountInfo*/ + +static FLStatus TFFSWriteQuickMountInfo(IOreq* ioreq) +{ + return flOK; +}/*TFFSWriteQuickMountInfo*/ + +static FLStatus TFFSGetQuickMountStatus(IOreq* ioreq) +{ + ioreq->irFlags = FL_ON; + return flOK; +}/*TFFSGetQuickMountStatus*/ + +#endif /* FL_NO_QUICK_MOUNT_FEATURE */ + +/********************************************************/ +/* */ +/* Mount related routines are obsolete for DOCH */ +/* Maintained in API only for backward compatibility */ +/* */ +/********************************************************/ +static FLStatus TFFSAbsMountVolume(IOreq* ioreq) +{ + FLByte partition; + FLStatus flStatus; + IOreq myIoreq; + DOCH_Error rc; + DOCH_DiskUserAttrWithBinary* pDiskUserAttr = (DOCH_DiskUserAttrWithBinary*) dochVol.intermediateBuf; + + partition = FL_GET_FLASH_PARTITION_FROM_HANDLE(ioreq); + + tffsset(&myIoreq, 0, sizeof(myIoreq)); + myIoreq.irHandle = ioreq->irHandle; + myIoreq.irData = dochVol.intermediateBuf; + rc = flDOCHGetDiskUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSAbsMountVolume(): flDOCHGetDiskUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault)? flHWProtection:TFFS_API_RET(rc); + } + /*Get some data from disk attributes sector*/ + if ((tffscmp(pDiskUserAttr->bMigrationSignature, + TFFS_API_MIGRATION_SIGNATURE, + sizeof(pDiskUserAttr->bMigrationSignature)) != 0) + || (!pDiskUserAttr->bIplPresent) + || (!pDiskUserAttr->bOtpPresent)) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSAbsMountVolume(): Device is not formated with TrueFFS. Either reformat the device or run upgrade utility.\n"); + return flBadFormat; + } + + /* check whether format with DD 1.1 beta or upper*/ + if (tffscmp(pDiskUserAttr->bFormatStartSignature, + TFFS_API_FORMAT_START_SIGNATURE, + sizeof(pDiskUserAttr->bFormatStartSignature)) == 0) + { + if (tffscmp(pDiskUserAttr->bFormatCompleteSignature, + TFFS_API_FORMAT_COMPLETE_SIGNATURE, + sizeof(pDiskUserAttr->bFormatCompleteSignature)) != 0) + { + DBG_PRINT_ERR(FLZONE_API,"TFFSAbsMountVolume(): No format completion signature \n"); + return flBadFormat; + } + }else + { /* Format with earlier versions*/ + /* retrieve last partition number*/ + FLByte bLastPartition; + rc = flDOCHIdentifyDiskOnChipDevice(tffsAPISetIoreq(&myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq), + 0,0,dochVol.intermediateBuf, 0,0)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSAbsMountVolume(): flDOCHIdentifyDiskOnChipDevice failed with status: 0x%x \n"), rc)); + return (rc==DOCH_DiskNotFound)? flUnknownMedia : TFFS_API_RET(rc); + } + bLastPartition = (FLByte)((DOCH_DeviceInfo*)dochVol.intermediateBuf)->wTotalNumOfPartitions -1; + + tffsAPISetIoreq(&myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq) + (bLastPartition << 4), 0,0, dochVol.intermediateBuf,0,0); + rc = flDOCHGetParitionUserAttributes(&myIoreq); + if((rc != DOCH_OK && rc!=DOCH_ProtectionFault) ||(rc==DOCH_ProtectionFault && bLastPartition==partition)) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSAbsMountVolume(): flDOCHGetParitionUserAttributes failed with status: 0x%x \n"), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : TFFS_API_RET(rc); + /* no failure if last partition is hidden and we try to mount different partition*/ + } + + if (rc!=DOCH_ProtectionFault) + { /* if last partition is not hidden we can check format completeness*/ + if ((FLByte)((DOCH_PartitionUserAttrWithBinary*)dochVol.intermediateBuf)->bType != PARTITION_TYPE_BDTL) + { + DBG_PRINT_ERR(FLZONE_API,"TFFSAbsMountVolume(): No format completion indication on last partition \n"); + return flBadFormat; + } + } + } + + flStatus = dochMountTL(partition, FL_GET_SOCKET_FROM_HANDLE(ioreq)); + if (flStatus == flOK) + { + if(dochVol.mountCount[partition] < 0x64) + dochVol.mountCount[partition]++; + } + return flStatus; +}/*TFFSAbsMountVolume*/ + +static FLStatus TFFSAbsDismountVolume(IOreq* ioreq) +{ + FLByte partition; + FLStatus rc; + partition = FL_GET_FLASH_PARTITION_FROM_HANDLE(ioreq); + if(dochVol.mountCount[partition] == 0) + { + return flNotMounted; + } + + if(dochVol.mountCount[partition] > 0) + { + rc = dochDismountTL(partition); + if (rc == flOK) + { + dochVol.mountCount[partition]--; + } + } + else + rc = flNotMounted; + return rc; +}/*TFFSAbsDismountVolume*/ + + +/*----------------------------------------------------------------------*/ +/* Function name : TFFSCheckVolume*/ +/* Description : */ +/* Return type : static FLStatus */ +/* Argument : IOreq* ioreq*/ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSCheckVolume(IOreq* ioreq) +{ + FLStatus flStatus; + if(dochVol.mountCount[FL_GET_FLASH_PARTITION_FROM_HANDLE(ioreq)] > 0) + flStatus = flOK; + else + flStatus = flNotMounted; + return flStatus; +}/*TFFSCheckVolume*/ + +#ifndef FL_READ_ONLY +/*----------------------------------------------------------------------*/ +/* T F F S D e f r a g m e n t V o l u m e */ +/* */ +/* Performs a general defragmentation and recycling of non-writable */ +/* Flash areas, to achieve optimal write speed. */ +/* */ +/* NOTE: The required number of sectors (in irLength) may be changed */ +/* (from another execution thread) while defragmentation is active. In */ +/* particular, the defragmentation may be cut short after it began by */ +/* modifying the irLength field to 0. */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irLength : Minimum number of sectors to make available for */ +/* writes. */ +/* */ +/* Returns: */ +/* irLength : Actual number of sectors available for writes */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSDefragmentVolume(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq myIoreq; + FLSDword request = ioreq->irLength; + + TFFS_API_GET_UNIT_SIZE(myIoreq, ioreq, rc, flStatus); + /*Return values*/ + /*=============*/ + switch(request) + { + case FL_MINIMAL_DEFRAGMENTATION: + case FL_MAXIMUM_DEFRAGMENTATION: + ioreq->irLength = dochVol.dwVirtualUnitSizeInSectors; + return flNotEnoughMemory; + + case FL_STATIC_WEAR_LEVELING_DELAYED: + case FL_STATIC_WEAR_LEVELING_NOW: + case FL_STATIC_WEAR_LEVELING_ON: + case FL_STATIC_WEAR_LEVELING_OFF: + ioreq->irLength = dochVol.dwVirtualUnitSizeInSectors; + break; + + default: + if(request > 0) + ioreq->irLength = dochVol.dwVirtualUnitSizeInSectors; + else + { + if(request == 0) + ioreq->irLength = 0; + else + return flBadParameter; + } + return flNotEnoughMemory; + } + return flOK; +}/*TFFSDefragmentVolume()*/ + + + + + +/*********************************************************/ +/* Function name : tffsFormatSetProtectionAttribs*/ +/* Description : */ +/* Return type : FLStatus */ +/* Argument : FLByte bProtType*/ +/* Argument : DOCH_PartitionFormatInfoAPI* pPartitionFormatInfoAPI*/ +/* Argument : FLByte * bKey*/ +/* Argument : FLWord wKeyLen*/ +/*********************************************************/ +static FLStatus tffsFormatSetProtectionAttribs( FLByte bProtType, DOCH_PartitionFormatInfoAPI* pPartitionFormatInfoAPI, + FLByte * pKey, FLWord wKeyLen) +{ + FLBoolean read_protect, write_protect, change_protect, locked; +#ifdef FL_SLPP + FLBoolean slpp =FALSE; +#endif /*FL_SLPP*/ +#ifdef FL_SOTP + FLBoolean sotp =FALSE; +#endif /*FL_SOTP*/ + + read_protect = write_protect = change_protect = locked = FALSE; + /*Enabled Protections*/ + + if( (bProtType & READ_PROTECTED) == READ_PROTECTED) + read_protect = TRUE; + if( (bProtType & WRITE_PROTECTED) == WRITE_PROTECTED) + write_protect = TRUE; + if( (bProtType & CHANGEABLE_PROTECTION) == CHANGEABLE_PROTECTION) + change_protect = TRUE; + if( (bProtType & LOCK_ENABLED) == LOCK_ENABLED) + locked = TRUE; +#ifdef FL_SLPP + if ((bProtType & SECTOR_LEVEL_PROTECTION) == SECTOR_LEVEL_PROTECTION) + slpp=TRUE; +#endif /*FL_SLPP*/ +#ifdef FL_SOTP + if ((bProtType & FORMAT_SEQUENTIAL_OTP)==FORMAT_SEQUENTIAL_OTP) + sotp=TRUE; + + if (sotp) + { + pPartitionFormatInfoAPI->bSOTP =TRUE; + pPartitionFormatInfoAPI->dwOtpEnabled =TRUE; + change_protect =TRUE; /* lock of SOTP is performed later on and is not allowed if not changeable*/ + } +#endif /*FL_SOTP*/ + + /*Protection requested*/ + if(read_protect || write_protect) + { + pPartitionFormatInfoAPI->dwProtectionType = DOCH_PARTITION_PWD_PROTECTED; + + /*Specific protection*/ + if(read_protect) + { + pPartitionFormatInfoAPI->dwGuestAccessMode = DOCH_PART_ACCESS_MODE_NONE; + } + else /*write_protect*/ + { + pPartitionFormatInfoAPI->dwGuestAccessMode = DOCH_PART_ACCESS_MODE_RO; + } + } + else + { +#ifdef FL_SLPP + /*SLPP partition*/ + if(slpp) + pPartitionFormatInfoAPI->dwProtectionType = DOCH_PARTITION_SLPP_PROTECTED; + /*No protection requested or changeable protection only requested */ + else +#endif /*FL_SLPP*/ + pPartitionFormatInfoAPI->dwProtectionType = (change_protect!=FALSE)?DOCH_PARTITION_PWD_PROTECTED:DOCH_PARTITION_NOT_PROTECTED; + + pPartitionFormatInfoAPI->dwUserAccessMode = DOCH_PART_ACCESS_MODE_FULL; + pPartitionFormatInfoAPI->dwGuestAccessMode = DOCH_PART_ACCESS_MODE_FULL; + } + + /* lock notification */ + pPartitionFormatInfoAPI->dwLockControl = (locked==TRUE) ? DOCH_LOCK_ACTIVE : DOCH_LOCK_NOT_ACTIVE; + + /*Passkey*/ +#ifndef FL_SLPP + if(read_protect || write_protect || change_protect) +#else /*FL_SLPP*/ + if(read_protect || write_protect || change_protect||slpp) +#endif /*FL_SLPP*/ + { + tffscpy(pPartitionFormatInfoAPI->bPasskey, pKey, wKeyLen); + } + + + + return flOK; +}/*tffsFormatSetProtectionAttribs*/ + +#ifdef FL_FORMAT_VOLUME +/*----------------------------------------------------------------------*/ +/* T F F S F l a s h F o r m a t */ +/* */ +/* Performs formatting of the DiskOnChip. */ +/* All existing data is destroyed. */ +/* */ +/* Note : This routine is the format routine for OSAK 5.0 and up. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (0, 1, ...) */ +/* Partition number must be 0 */ +/* irFlags : */ +/* TL_NORMAL_FORMAT : Normal format */ +/* TL_LEAVE_SOME_PARTITIONS : Leave some of the previously */ +/* existing partitions */ +/* TL_DO_NOT_PERFORM_DOWNLOAD */ +/* irData : Address of FormatParams3 structure to use */ +/* (defined in format.h) */ +/* irLength : If the TL_LEAVE_SOME_PARTITIONS flag is set, */ +/* this field will indicate the number of partitions */ +/* to leave. */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSflashFormat(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + FLStatus myStatus; + IOreq myIoreq; + FLSNative i=0; + FLByte partNum=0, numOfBinaryPartitions; + +#ifdef BDK_ACCESS + FLByte totalNumOfPartitions; +#endif /*BDK_ACCESS*/ + + FormatParams3 FAR1 * FP3 = (FormatParams3 FAR1 *)ioreq->irData; + BDTLPartitionFormatParams3 FAR2 * bdtlUserParams; + +#ifdef BDK_ACCESS + BinaryPartitionFormatParams3 FAR2 * binUserParams; + FLSNative numOfBinaryParToLeave = 0; +#endif /*BDK_ACCESS*/ + + FLSNative total_num_of_partitions = (FP3->noOfBinaryPartitions + FP3->noOfBDTLPartitions); + FLSNative numOfParToLeave = 0; + FLByte bOtpPresent, bIplPresent; + FLWord lastRemainingPartition, wNumOfOriginalPartitions; + + FLByte* intBuf = dochVol.intermediateBuf; + DOCH_DiskUserAttrWithBinary* pDiskUserAttrWithBinary = (DOCH_DiskUserAttrWithBinary*)intBuf; + DOCH_PartitionUserAttrWithBinary* pPartitionUserAttrWithBinary = (DOCH_PartitionUserAttrWithBinary*)intBuf; + DOCH_PartitionFormatInfoAPI* pPartitionFormatInfoAPI = (DOCH_PartitionFormatInfoAPI*)intBuf; + DOCH_Socket* pDev; + +#ifdef BDK_ACCESS + FLDword dwPartitionTotalSize; +#endif /*BDK_ACCESS*/ + + DOCH_get_socket(pDev, FL_GET_SOCKET_FROM_HANDLE(ioreq)); + if( pDev==NULL ) + return flBadParameter; + + /*If binary partitions requested and no BDK support - return error*/ +#ifndef BDK_ACCESS + if(FP3->noOfBinaryPartitions > 0) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSflashFormat(): Binary partitions not supported when BDK_ACCESS Not Defined!\r\n"))); + return flBadParameter; + } +#endif /*BDK_ACCESS*/ + + /*Retrieve disk attributes*/ + tffsset(&myIoreq, 0, sizeof(myIoreq)); + myIoreq.irHandle = FL_GET_SOCKET_FROM_HANDLE(ioreq); + myIoreq.irData = intBuf; + rc = flDOCHGetDiskUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSflashFormat(): flDOCHGetDiskUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault)? flHWProtection:TFFS_API_RET(rc); + } + + /* Get some data from disk attributes sector */ + numOfBinaryPartitions = pDiskUserAttrWithBinary->bNumOfBinaryPartitions; + bIplPresent = pDiskUserAttrWithBinary->bIplPresent; + bOtpPresent = pDiskUserAttrWithBinary->bOtpPresent; + +#ifdef BDK_ACCESS + totalNumOfPartitions = (FLByte)pDev->wTotalNumOfPartitions; +#endif /*BDK_ACCESS*/ + + /* check for corruption during format or wrong format */ + /* wrong signature */ + if( (tffscmp(pDiskUserAttrWithBinary->bMigrationSignature, TFFS_API_MIGRATION_SIGNATURE, + sizeof(pDiskUserAttrWithBinary->bMigrationSignature)) != 0) + /* disk attributes not match no. of partitions */ + || (pDev->wTotalNumOfPartitions<2 && bIplPresent && bOtpPresent) + /* there are enough partitions but IPL or/and OTP indication corrupted */ + || (pDev->wTotalNumOfPartitions>2 && (bIplPresent!=1 || bOtpPresent!=1)) ) + { + bIplPresent = 0; + bOtpPresent = 0; + numOfBinaryPartitions = 0; + } + +#ifdef BDK_ACCESS + /*Calculate how many binary partition to LEAVE*/ + if(ioreq->irFlags == TL_LEAVE_BINARY_AREA) + { + numOfParToLeave = numOfBinaryPartitions; + numOfBinaryParToLeave = numOfBinaryPartitions; + } + else + { + if(ioreq->irFlags == TL_LEAVE_SOME_BINARY_AREA) + { + numOfParToLeave = ioreq->irLength; + numOfBinaryParToLeave = TFFSMIN(numOfBinaryPartitions, numOfParToLeave); + } + else + { + numOfParToLeave = 0; + numOfBinaryParToLeave = 0; + } + } + + if(numOfParToLeave > totalNumOfPartitions) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSflashFormat(): numOfParToLeave > totalNumOfPartitions \r\n "); + return flBadParameter; + } + + if((numOfBinaryParToLeave + FP3->noOfBinaryPartitions) > MAX_BINARY_PARTITIONS_PER_DRIVE) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSflashFormat(): Number of binary partitions exceed maximum allowed.\r\n "); + return flBadParameter; + } + + if((numOfParToLeave > numOfBinaryPartitions) && (FP3->noOfBinaryPartitions > 0)) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSflashFormat(): Can`t create Binary after BDTL.\r\n "); + return flBadParameter; + } + +#else /*BDK_ACCESS*/ + if(ioreq->irFlags == TL_LEAVE_SOME_PARTITIONS) + { + numOfParToLeave = ioreq->irLength; + } + else + { + numOfParToLeave = 0; + } +#endif /*BDK_ACCESS*/ + + /* Check that total number of partitions AFTER format does not exceed FL_VOLUMES */ + if((numOfParToLeave + FP3->noOfBinaryPartitions + FP3->noOfBDTLPartitions) > FL_VOLUMES) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSflashFormat(): Number of partitions exceed maximum allowed.\r\n "); + return flBadParameter; + } + + /* Leaving all existing partitions is not allowed */ + tffsset(&myIoreq, 0, sizeof(myIoreq)); + myIoreq.irHandle = ioreq->irHandle; + myStatus = TFFSCountVolumes(&myIoreq); + if(myStatus != flOK) + return myStatus; + if(numOfParToLeave >= (FLSNative)myIoreq.irFlags) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSflashFormat(): Leaving all existing partitions is not allowed!!!.\r\n "); + return flBadParameter; + } + + + /*Calculate number of remaining partitions*/ + lastRemainingPartition = (numOfParToLeave + bOtpPresent + bIplPresent); + + /*Retrieve DOCH extended info structure*/ + /*-------------------------------------*/ + TFFS_API_GET_UNIT_SIZE(myIoreq, ioreq, rc, flStatus); + wNumOfOriginalPartitions = ((DOCH_DeviceInfo*)intBuf)->wTotalNumOfPartitions; + + /*Clear partition attributes for partitions to be deleted */ + if(lastRemainingPartition > 0) + { + tffsset(intBuf, 0, DOCH_SECTOR_SIZE); + tffsset(&myIoreq, 0, sizeof(myIoreq)); + myIoreq.irData = intBuf; + for(i=lastRemainingPartition; i < wNumOfOriginalPartitions; i++) + { + myIoreq.irHandle = FL_GET_SOCKET_FROM_HANDLE(ioreq) + (i << 4); + rc = flDOCHSetParitionUserAttributes(&myIoreq); + if( rc!=DOCH_OK ) + { + return (rc==DOCH_ProtectionFault)? flHWProtection:TFFS_API_RET(rc); + } + } + } + + /*Set numOfBinaryPartitions*/ +#ifdef BDK_ACCESS + numOfBinaryPartitions = numOfBinaryParToLeave; +#else /*BDK_ACCESS*/ + numOfBinaryPartitions = 0; +#endif /*BDK_ACCESS*/ + + /*Set programmer name, programmer version and TFFS version*/ + tffsset(intBuf, 0, DOCH_SECTOR_SIZE); + pDiskUserAttrWithBinary->bNumOfBinaryPartitions = numOfBinaryPartitions; + pDiskUserAttrWithBinary->bIplPresent = bIplPresent; + pDiskUserAttrWithBinary->bOtpPresent = bOtpPresent; + tffscpy(&pDiskUserAttrWithBinary->bProgrammerName, FL_PROGRAMMER_NAME, 4); + tffscpy(&pDiskUserAttrWithBinary->bProgrammerVersion, FL_PROGRAMMER_VERSION, 4); + tffscpy(&pDiskUserAttrWithBinary->bTFFSVersion, TrueFFSVersion, 4); + tffscpy(pDiskUserAttrWithBinary->bMigrationSignature, TFFS_API_MIGRATION_SIGNATURE, + sizeof(pDiskUserAttrWithBinary->bMigrationSignature)); + /* starting DD 1.1 beta - indication on format start and format complete*/ + tffscpy(pDiskUserAttrWithBinary->bFormatStartSignature, TFFS_API_FORMAT_START_SIGNATURE, + sizeof(pDiskUserAttrWithBinary->bFormatStartSignature)); + tffsset(&myIoreq, 0, sizeof(myIoreq)); + myIoreq.irHandle = FL_GET_SOCKET_FROM_HANDLE(ioreq); + myIoreq.irData = intBuf; + rc = flDOCHSetDiskUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSflashFormat(): flDOCHSetDiskUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault)? flHWProtection:TFFS_API_RET(rc); + } + dochVol.numOfBinaryPartitions = numOfBinaryPartitions; + + if (bOtpPresent == 0) + total_num_of_partitions++; + if (bIplPresent == 0) + total_num_of_partitions++; + + if( (wNumOfOriginalPartitions > 2) ||/* more, than IPL and OTP present */ + (bIplPresent==0 && bOtpPresent == 0 && numOfBinaryPartitions == 0) )/* or not proper format */ + { + /*Delete partitions not marked to "leave" (if such exists)*/ + tffsAPISetIoreq( &myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq), 0,0,0,0xFF, + numOfParToLeave + bIplPresent + bOtpPresent); + rc = flDOCHDeletePartitions(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSflashFormat(): flDOCHDeletePartitions failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault)? flHWProtection:TFFS_API_RET(rc); + } + } + + /*Set IPL partition*/ + if(bIplPresent == 0) + { + /* add IPL partition, update it's attributes and disk attributes */ + checkStatus( tffsApiAddOtpIPL(TRUE, &myIoreq, ioreq) ); + tffsset(intBuf, 0xff, DOCH_SECTOR_SIZE); + for (i = 0; i < TFFS_API_8K_NORMAL_IPL_SIZE ; i++) + { + tffsAPISetIoreq( &myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq), + (DOCH_IPL_MODE_8KB_WINDOW|DOCH_IPL_MODE_ADDRESS_SHIFT_IN_AFFECT), + 0, dochVol.intermediateBuf, 1, TFFS_API_8K_NORMAL_IPL_SIZE); + if (i == 0) + myIoreq.irFlags |= DOCH_IPL_WRITE_FIRST_CHUNK; + rc = flDOCHWriteIPL(&myIoreq); + if (rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSflashFormat(): Failed writing default IPL. status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \n"), rc)); + TFFS_API_RET_PART_FLSTATUS(rc,flWriteFault); + } + } + dochVol.iplExists = 1; + bIplPresent = 1; + }/* IPL should be added */ + + /*Set OTP partition*/ + if(bOtpPresent == 0) + { + checkStatus( tffsApiAddOtpIPL(FALSE, &myIoreq, ioreq) ); + dochVol.otpExists = 1; + bOtpPresent = 1; + }/*OTP partition should be added */ + + partNum = bOtpPresent + bIplPresent + numOfParToLeave; + +#ifdef BDK_ACCESS + + binUserParams = FP3->binaryPartitionInfo; + + /*Perform for every binary partition*/ + /*----------------------------------*/ + for(i=0; i< FP3->noOfBinaryPartitions; i++) + { + /* Fill DOCH_PartitionFormatInfoAPI structure from FormatParams3 structure */ + /*==========================================================================*/ + tffsset(intBuf, 0, sizeof(DOCH_PartitionFormatInfoAPI)); + + /* standard migration format params */ + TFFS_API_SET_MIG_STD_PART_PRMS(pPartitionFormatInfoAPI, binUserParams->protectionType); + + /* protection features */ + checkStatus( tffsFormatSetProtectionAttribs(binUserParams->protectionType, pPartitionFormatInfoAPI, + binUserParams->protectionKey, sizeof(binUserParams->protectionKey)) ); + + + /*Partition size (must be FL_LENGTH_IN_BYTES)*/ + pPartitionFormatInfoAPI->nPartitionSize = (binUserParams->length & 0x1FF) ? + ((binUserParams->length)>>DOCH_SECTOR_SIZE_BITS)+1 : ((binUserParams->length)>>DOCH_SECTOR_SIZE_BITS); + + /*Round partition size to Unit Size*/ + pPartitionFormatInfoAPI->nPartitionSize = + (pPartitionFormatInfoAPI->nPartitionSize+dochVol.dwVirtualUnitSizeInSectors-1) & (~(dochVol.dwVirtualUnitSizeInSectors-1)); + + if( pPartitionFormatInfoAPI->nPartitionSize == 0 ) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSflashFormat(): cannot add zero length binary partition "); + return flBadParameter; + } + + /*Add partition*/ + tffsAPISetIoreq(&myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq), 0,0, intBuf,0,0); + rc = flDOCHAddPartition(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSflashFormat(): flDOCHAddPartition (Binary) failed with status: 0x%x "), rc)); + return TFFS_API_RET(rc); + } +#ifdef HW_PROTECTION + /*Authenticate partition*/ + if(((binUserParams->protectionType & PROTECTABLE) == PROTECTABLE) && + ((binUserParams->protectionType & (READ_PROTECTED | WRITE_PROTECTED)) != 0)) + { + checkStatus( tffsApiAuthPartition(&myIoreq, ioreq, partNum, binUserParams->protectionKey, + sizeof(binUserParams->protectionKey))); + } +#endif /*HW_PROTECTION*/ + + /*Retrieve partition info*/ + tffsAPISetIoreq(&myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq) + (partNum << 4), 0,0, intBuf,0,0); + rc = flDOCHPartitionInfo(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSflashFormat(): flDOCHPartitionInfo failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : TFFS_API_RET(rc); + } + dwPartitionTotalSize = ((DOCH_PartitionInfo*)intBuf)->nPartitionSize; + + /*Retrieve current attributes*/ + rc = flDOCHGetParitionUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSflashFormat(): flDOCHGetParitionUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : TFFS_API_RET(rc); + } + + /* Update the partition attributes and write them back to device */ + /*-------------*/ + /*Set type to binary*/ + pPartitionUserAttrWithBinary->bType = PARTITION_TYPE_BINARY; + pPartitionUserAttrWithBinary->binPartHeader.dwPartitionFlags = binUserParams->flags; + /*Set signature*/ + tffscpy( pPartitionUserAttrWithBinary->binPartHeader.subPartitions[0].bSignature, + binUserParams->sign, BDK_SIGNATURE_NAME); + /*Set length*/ + pPartitionUserAttrWithBinary->binPartHeader.subPartitions[0].dwSize = dwPartitionTotalSize; + /*Set # of sub-partitions to 1*/ + pPartitionUserAttrWithBinary->binPartHeader.bNumOfSubPartitions = 1; + /*Set DPS attribute*/ + pPartitionUserAttrWithBinary->bDPSFwd = 0; /*Not used*/ + pPartitionUserAttrWithBinary->bDPSBwd = 0; /*Not used*/ + /*Set protection attribute*/ + pPartitionUserAttrWithBinary->bChangableProtection = ((binUserParams->protectionType & CHANGEABLE_PROTECTION) == CHANGEABLE_PROTECTION); + pPartitionUserAttrWithBinary->bProtected = ((binUserParams->protectionType & PROTECTABLE) == PROTECTABLE); + /*Set attributes back to device*/ + rc = flDOCHSetParitionUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSflashFormat(): flDOCHSetParitionUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : TFFS_API_RET(rc); + } + + /* Update the disk attributes and write them back to device */ + /*-------------*/ + tffsAPISetIoreq(&myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq), 0,0, intBuf,0,0); + rc = flDOCHGetDiskUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSflashFormat(): flDOCHGetDiskUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : TFFS_API_RET(rc); + } + pDiskUserAttrWithBinary->bNumOfBinaryPartitions = numOfBinaryPartitions + 1; + tffsAPISetIoreq(&myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq), 0,0, intBuf,0,0); + rc = flDOCHSetDiskUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSflashFormat(): flDOCHSetDiskUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : TFFS_API_RET(rc); + } + +#ifdef HW_PROTECTION + /*Authenticate partition*/ + if((((binUserParams->protectionType & PROTECTABLE) == PROTECTABLE) && + (binUserParams->protectionType & (READ_PROTECTED | WRITE_PROTECTED)) != 0) && + (ioreq->irFlags & TL_DO_NOT_PERFORM_DOWNLOAD) == 0) + { + tffsset(&myIoreq, 0, sizeof(myIoreq)); + myIoreq.irHandle = FL_GET_SOCKET_FROM_HANDLE(ioreq); + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&myIoreq, partNum); + myIoreq.irFlags = DOCH_ACCESS_USER_PASSWORD; + rc = flDOCHDisablePartAccess(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSflashFormat(): flDOCHDisablePartAccess failed with status: 0x%x "), rc)); + return TFFS_API_RET(rc); + } + } +#endif /*HW_PROTECTION*/ + + numOfBinaryPartitions++; + partNum++; + dochVol.numOfBinaryPartitions = numOfBinaryPartitions; + binUserParams++; + } +#endif /*BDK_ACCESS*/ + + /* fix the partition size to be zero - spend on the reminder of the disk + required for last partition */ + FP3->BDTLPartitionInfo[FP3->noOfBDTLPartitions-1].length = 0; + + /*Perform for every bdtl partition*/ + /*--------------------------------*/ + bdtlUserParams = FP3->BDTLPartitionInfo; + for(i=0; i< FP3->noOfBDTLPartitions; i++) + { + /* Fill DOCH_PartitionFormatInfoAPI structure from FormatParams3 structure */ + /*==========================================================================*/ + tffsset(intBuf, 0, sizeof(DOCH_PartitionFormatInfoAPI)); + + /* standard migration format params */ + TFFS_API_SET_MIG_STD_PART_PRMS(pPartitionFormatInfoAPI, bdtlUserParams->protectionType); + + /* protection features */ + checkStatus( tffsFormatSetProtectionAttribs(bdtlUserParams->protectionType, pPartitionFormatInfoAPI, + bdtlUserParams->protectionKey, sizeof(bdtlUserParams->protectionKey)) ); + + /*Partition size*/ + /*--------------*/ + switch(bdtlUserParams->lengthType) + { + case FL_LENGTH_IN_BYTES: + /*Convert to Sectors*/ + pPartitionFormatInfoAPI->nPartitionSize = + (bdtlUserParams->length & 0x1FF) ? + ((bdtlUserParams->length)>>DOCH_SECTOR_SIZE_BITS)+1 : ((bdtlUserParams->length)>>DOCH_SECTOR_SIZE_BITS); + break; + + case FL_LENGTH_IN_SECTORS: + /*Already in sectors*/ + pPartitionFormatInfoAPI->nPartitionSize = bdtlUserParams->length; + break; + + case FL_LENGTH_IN_UNITS: + pPartitionFormatInfoAPI->nPartitionSize = (bdtlUserParams->length << DOCH_SECTORS_IN_UNIT_BITS); + break; + + case FL_LENGTH_IN_PERCENTS: + /*Not supported*/ + DBG_PRINT_ERR(FLZONE_API, "TFFSflashFormat(): FL_LENGTH_IN_PERCENTS Not supported\r\n "); + return flBadParameter; + + case FL_LENGTH_IN_CYLINDERS: + /*Not supported*/ + DBG_PRINT_ERR(FLZONE_API, "TFFSflashFormat(): FL_LENGTH_IN_CYLINDERS Not supported\r\n "); + return flBadParameter; + + default: + DBG_PRINT_ERR(FLZONE_API, "TFFSflashFormat(): Unsupported Normal area length type\r\n "); + return flBadParameter; + } + + /*Round partition size to Unit Size*/ + /*---------------------------------*/ + pPartitionFormatInfoAPI->nPartitionSize = + ((pPartitionFormatInfoAPI->nPartitionSize + + dochVol.dwVirtualUnitSizeInSectors - 1) & (~(dochVol.dwVirtualUnitSizeInSectors-1))); + + /*Fast area size*/ + /*--------------*/ + switch(bdtlUserParams->fastAreaLengthType) + { + case FL_LENGTH_IN_BYTES: + pPartitionFormatInfoAPI->nFastAreaSize = (bdtlUserParams->fastAreaLength >> DOCH_SECTOR_SIZE_BITS); + pPartitionFormatInfoAPI->dwFastAreaSizeType = DOCH_FAST_AREA_TYPE_SECTORS; + break; + + case FL_LENGTH_IN_SECTORS: + pPartitionFormatInfoAPI->nFastAreaSize = bdtlUserParams->fastAreaLength; + pPartitionFormatInfoAPI->dwFastAreaSizeType = DOCH_FAST_AREA_TYPE_SECTORS; + break; + + case FL_LENGTH_IN_UNITS: + /*Not supported*/ + DBG_PRINT_ERR(FLZONE_API, "TFFSflashFormat(): FL_LENGTH_IN_UNITS Not supported\r\n "); + return flBadParameter; + /*break;*/ + + case FL_LENGTH_IN_PERCENTS: + /*Not supported*/ + DBG_PRINT_ERR(FLZONE_API, "TFFSflashFormat(): FL_LENGTH_IN_PERCENTS Not supported\r\n "); + return flBadParameter; + + + case FL_LENGTH_IN_CYLINDERS: + /*Not supported*/ + DBG_PRINT_ERR(FLZONE_API, "TFFSflashFormat(): FL_LENGTH_IN_CYLINDERS Not supported\r\n "); + return flBadParameter; + /*break;*/ + + case FL_LENGTH_ALL: + pPartitionFormatInfoAPI->nFastAreaSize = TL_ENHANCED_PERFORMANCE; + pPartitionFormatInfoAPI->dwFastAreaSizeType = DOCH_FAST_AREA_TYPE_PERCENT; + break; + + default: + DBG_PRINT_ERR(FLZONE_API, "TFFSflashFormat(): Unsupported Fast area length type\r\n "); + return flBadParameter; + /*break;*/ + } + pPartitionFormatInfoAPI->wFastAreaFactor = bdtlUserParams->fastAreaVirtualFactor; + + /*Round fast area size up to Unit Size*/ + /*------------------------------------*/ + if (pPartitionFormatInfoAPI->dwFastAreaSizeType == DOCH_FAST_AREA_TYPE_SECTORS) + { + pPartitionFormatInfoAPI->nFastAreaSize = + ((pPartitionFormatInfoAPI->nFastAreaSize + + dochVol.dwVirtualUnitSizeInSectors - 1) & (~(dochVol.dwVirtualUnitSizeInSectors-1))); + } + + /*Add partition*/ + /*-------------*/ + tffsAPISetIoreq(&myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq), 0,0, intBuf,0,0); + rc = flDOCHAddPartition(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSflashFormat(): flDOCHAddPartition (Bdtl) failed with status: 0x%x "), rc)); + return TFFS_API_RET(rc); + } + + /*Authenticate partition*/ + if(((bdtlUserParams->protectionType & PROTECTABLE) == PROTECTABLE) && + (bdtlUserParams->protectionType & (READ_PROTECTED | WRITE_PROTECTED)) != 0) + { + checkStatus( tffsApiAuthPartition(&myIoreq, ioreq, partNum, + bdtlUserParams->protectionKey, sizeof(bdtlUserParams->protectionKey)) ); + } + + + /*Retrieve current attributes*/ + tffsAPISetIoreq(&myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq) + (partNum << 4), 0,0, intBuf,0,0); + rc = flDOCHGetParitionUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSflashFormat(): flDOCHGetParitionUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : TFFS_API_RET(rc); + } + + /*Set type to BDTL*/ + pPartitionUserAttrWithBinary->bType = PARTITION_TYPE_BDTL; + /*Set DPS attribute*/ + pPartitionUserAttrWithBinary->bDPSFwd = 0; /*Not used*/ + pPartitionUserAttrWithBinary->bDPSBwd = 0; /*Not used*/ + /*Set protection attribute*/ + pPartitionUserAttrWithBinary->bChangableProtection = ((bdtlUserParams->protectionType & CHANGEABLE_PROTECTION) == CHANGEABLE_PROTECTION); + pPartitionUserAttrWithBinary->bProtected = ((bdtlUserParams->protectionType & PROTECTABLE) == PROTECTABLE); + /*Set attributes back to device*/ + rc = flDOCHSetParitionUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSflashFormat(): flDOCHSetParitionUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : TFFS_API_RET(rc); + } + +#ifdef FL_SOTP + if (bdtlUserParams->protectionType & FORMAT_SEQUENTIAL_OTP/*pPartitionFormatInfoAPI->bSOTP*/) + { + /*lock SOTP partition*/ + + pPartitionFormatInfoAPI->bSOTP =TRUE; + pPartitionFormatInfoAPI->dwOtpEnabled =TRUE; + + + myIoreq.irHandle = ((FL_GET_SOCKET_FROM_HANDLE(ioreq))|((partNum)<<4)); + rc = flDOCHSetParitionProtection(tffsAPISetIoreq(&myIoreq, myIoreq.irHandle,(DOCH_LOCK_AS_OTP|DOCH_SEQUENTIAL_OTP),0,pPartitionFormatInfoAPI,0,0)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSflashFormat()(): flDOCHSetParitionProtection Failed with status : "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : TFFS_API_RET(rc) ; + } + + } +#endif /*FL_SOTP*/ + + /*Authenticate partition*/ + if (((bdtlUserParams->protectionType & PROTECTABLE) == PROTECTABLE) && + ((ioreq->irFlags & TL_DO_NOT_PERFORM_DOWNLOAD) == 0)) + { + tffsset(&myIoreq, 0, sizeof(myIoreq)); + myIoreq.irHandle = FL_GET_SOCKET_FROM_HANDLE(ioreq); + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&myIoreq, partNum); + myIoreq.irFlags = DOCH_ACCESS_USER_PASSWORD; + rc = flDOCHDisablePartAccess(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSflashFormat(): flDOCHDisablePartAccess failed with status: 0x%x "), rc)); + return TFFS_API_RET(rc); + } + } + partNum++; + bdtlUserParams++; + } + + /* starting DD 1.1 beta - add format complete indication*/ + tffsAPISetIoreq(&myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq), 0,0, intBuf, 0,0); + rc = flDOCHGetDiskUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSflashFormat(): flDOCHGetDiskUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault)? flHWProtection : TFFS_API_RET(rc); + } + tffscpy(pDiskUserAttrWithBinary->bFormatCompleteSignature, TFFS_API_FORMAT_COMPLETE_SIGNATURE, + sizeof(pDiskUserAttrWithBinary->bFormatCompleteSignature)); + rc = flDOCHSetDiskUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSflashFormat(): flDOCHSetDiskUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault)? flHWProtection : TFFS_API_RET(rc); + } + return flOK; +}/* TFFSFlashFormat() */ + + +/*----------------------------------------------------------------------*/ +/* T F F S U n f o r m a t */ +/* */ +/* Erase the entire media returning the DiskOnChip to it's virgin state */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (0, 1, ...) */ +/* Partition number must be 0 */ +/* irPath : Pointer to progress call back routine, or NULL */ +/* irFlags : reserved ( 0 ) */ +/* irData : reserved (NULL) */ +/* irLength : reserved ( 0 ) */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSUnFormat(IOreq* ioreq) +{ + FLStatus status; + DOCH_Error rc; + IOreq myIoreq; + FLExtendedDiskInfo extInfo; + FLByte i; + + tffsset(&myIoreq, 0, sizeof(myIoreq)); + + /*Retrieve # of partitions*/ + myIoreq.irHandle = (ioreq->irHandle & 0xF); + myIoreq.irCount = FL_EXT_INFO_NO_SPEC_PART; + myIoreq.irFlags = FL_BDK_PARTITION; + myIoreq.irData = &extInfo; + status = TFFSGetExtendedDiskInfo(&myIoreq); + /* if GetExtendedDiskInfo fails (bad format) force deletion of partitions + do not return status*/ + if (status ==flOK) + { + /*Check that all partitions are not actively protected + If so - return flHWProtection*/ + for(i = 0; iirHandle, 0,0, dochVol.intermediateBuf,0,0); + rc = flDOCHPartitionInfo(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSEraseBD(): flDOCHPartitionInfo failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : TFFS_API_RET(rc); + } + numOfSectors = ((DOCH_PartitionInfo*)dochVol.intermediateBuf)->nPartitionSize; + + /* check protection */ + tffsAPISetIoreq(&myIoreq, ioreq->irHandle, 0,0, NULL,0,0); + status = TFFSIdentifyProtection(&myIoreq); + if(status != flOK && status != flNotProtected) + return status; + if((myIoreq.irFlags & (WRITE_PROTECTED)) && ((myIoreq.irFlags & KEY_INSERTED)==0)) + return flHWProtection; + + /*Erase the entire partition*/ + /*--------------------------*/ + + tffsAPISetIoreq(&myIoreq, ioreq->irHandle, 0,0,NULL,0,numOfSectors); + rc = flDOCHWipeSectors(&myIoreq); + + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSEraseBD(): flDOCHErasePartition failed with status: 0x%x "), rc)); + TFFS_API_RET_PART_FLSTATUS(rc, TFFS_API_RET(rc)); + } + return flOK; +}/*TFFSEraseBD()*/ +#endif /*FL_FORMAT_VOLUME*/ +#endif /*FL_READ_ONLY*/ + +#ifdef FL_ABS_READ_WRITE +/*----------------------------------------------------------------------*/ +/* f l A b s R e a d */ +/* */ +/* Reads absolute sectors by sector no. */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irData : Address of user buffer to read into */ +/* irSectorNo : First sector no. to read (sector 0 is the */ +/* DOS boot sector). */ +/* irSectorCount : Number of consecutive sectors to read */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors actually read */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSAbsRead(IOreq* ioreq, FLSDword * pIrCount) +{ + DOCH_Error rc; + FLSDword dwsOrigIrCount=ioreq->irCount; + + /*Read required sectors*/ + /*---------------------*/ +#ifdef FL_DMA_CONFIG + if( (((FLDword)ioreq->irData & 3) == 0) && (gIsDMAEnabled == DOCH_GLOBAL_BOOL_PATTERN) ) + { + ioreq->irFlags |= DOCH_USE_DMA; + } +#endif /* FL_DMA_CONFIG */ +#ifdef FL_USE_BURST_MODE_READ + if((((FLDword)ioreq->irData & 3) == 0) && (tffs_burst_enabled == TRUE)) /* andrayk Nov 01 2007: enabling burst at runtime */ + { + ioreq->irFlags |= DOCH_USE_BURST; + } +#endif /* FL_USE_BURST_MODE_READ */ + + rc = flDOCHReadPartitionSectors(ioreq); + if(rc != DOCH_OK) + { + (*pIrCount) = dwsOrigIrCount - ioreq->irCount; /*update number of sectors which is read */ + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSAbsRead(): flDOCHReadPartitionSectors failed with status: 0x%x "), rc)); + TFFS_API_RET_PART_FLSTATUS(rc, flReadFault); + } + + (*pIrCount) = dwsOrigIrCount; + return flOK; +}/*TFFSAbsRead()*/ + + +/*----------------------------------------------------------------------*/ +/* Function name : TFFSAbsAddress*/ +/* Description : dummy function */ +/* Return type : static FLStatus */ +/* Argument : IOreq* ioreq*/ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSAbsAddress(IOreq* ioreq) +{ + return flFeatureNotSupported; +}/*TFFSAbsAddress()*/ + + +#ifndef FL_READ_ONLY +/*----------------------------------------------------------------------*/ +/* f l A b s W r i t e */ +/* */ +/* Writes absolute sectors by sector no. */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irData : Address of user buffer to write from */ +/* irSectorNo : First sector no. to write */ +/* irSectorCount : Number of consecutive sectors to write */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors actually written */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSAbsWrite(IOreq* ioreq) +{ + DOCH_Error rc; + FLSDword dwOrigIrCount = ioreq->irCount; + + /*Write required sectors*/ +#ifdef FL_USE_DMA_ON_WRITE /* should be changed to FL_DMA_CONFIG */ + if( (((FLDword)ioreq->irData & 3) == 0) && (gIsDMAEnabled == DOCH_GLOBAL_BOOL_PATTERN) ) + ioreq->irFlags |= DOCH_USE_DMA; +#endif /*FL_USE_DMA_ON_WRITE*/ + rc = flDOCHWritePartitionSectors(ioreq); + if(rc != DOCH_OK) + { + ioreq->irCount = dwOrigIrCount - ioreq->irCount; /*update number of sectors which is written */ + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSAbsWrite(): flDOCHWritePartitionSectors failed with status: 0x%x "), rc)); + TFFS_API_RET_PART_FLSTATUS(rc, flWriteFault); + } + + ioreq->irCount = dwOrigIrCount; + return flOK; +}/*TFFSAbsWrite()*/ + +/*----------------------------------------------------------------------*/ +/* f l A b s D e l e t e */ +/* */ +/* Marks absolute sectors by sector no. as deleted. */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irSectorNo : First sector no. to delete */ +/* irSectorCount : Number of consecutive sectors to delete */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors actually deleted */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSAbsDelete(IOreq* ioreq) +{ + /* FreeSectors does not perform any operation in mDoc H3 + therefore this call is removed*/ +#ifdef FL_SUPPORT_FREE_SECTORS + DOCH_Error rc; + + /*Free required sectors*/ + /*---------------------*/ + rc = flDOCHFreeSectors(ioreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSAbsDelete(): flDOCHFreeSectors failed with status: 0x%x "), rc)); + TFFS_API_RET_PART_FLSTATUS(rc, TFFS_API_RET(rc)); + } +#endif /*FL_SUPPORT_FREE_SECTORS*/ + return flOK; +}/*TFFSAbsDelete*/ + +/*----------------------------------------------------------------------*/ +/* f l A b s S e c u r e D e l e t e */ +/* */ +/* Marks absolute sectors by sector no. as deleted making sure no */ +/* previous copy exists. */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irSectorNo : First sector no. to delete */ +/* irSectorCount : Number of consecutive sectors to delete */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors actually deleted */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSAbsSecureDelete(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq myIoreq; + FLDword numOfSectors; + FLStatus status; + + /* check parameters before initialize wipe operations */ + /*----------------------------------------------------*/ + tffsAPISetIoreq(&myIoreq, ioreq->irHandle, 0,0, dochVol.intermediateBuf,0,0); + rc = flDOCHPartitionInfo(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSEraseBD(): flDOCHPartitionInfo failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : TFFS_API_RET(rc); + } + numOfSectors = ((DOCH_PartitionInfo*)dochVol.intermediateBuf)->nPartitionSize; + + /* check partition limits */ + if ((FLDword)(ioreq->irSectorNo+ioreq->irSectorCount)>numOfSectors) + { + return flBadParameter; + } + + /* check protection */ + tffsAPISetIoreq(&myIoreq, ioreq->irHandle, 0,0, NULL,0,0); + status = TFFSIdentifyProtection(&myIoreq); + if(status != flOK && status != flNotProtected) + return status; + if((myIoreq.irFlags & (WRITE_PROTECTED)) && ((myIoreq.irFlags & KEY_INSERTED)==0)) + return flHWProtection; + + tffsAPISetIoreq(&myIoreq, ioreq->irHandle, 0,0,NULL,ioreq->irSectorNo,ioreq->irSectorCount); + rc = flDOCHWipeSectors(&myIoreq); + + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSAbsSecureDelete(): flDOCHEraseSectors failed with status: 0x%x "), rc)); + TFFS_API_RET_PART_FLSTATUS(rc, TFFS_API_RET(rc)); + } + return flOK; +}/*TFFSAbsSecureDelete()*/ + +#endif /*FL_READ_ONLY*/ +#endif /*FL_ABS_READ_WRITE*/ + +/*----------------------------------------------------------------------*/ +/* f l G e t P h y s i c a l I n f o */ +/* */ +/* Get physical information of the media. The information includes */ +/* JEDEC ID, unit size and media size. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (0,1,..) */ +/* irData : Address of user buffer to read physical */ +/* information into. */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/* irLength : Window base address. note mast be cast to */ +/* unsigned. */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSGetPhysicalInfo(IOreq* ioreq) +{ + IOreq myIoreq; + DOCH_Error rc = DOCH_OK; + PhysicalInfo FAR1 * physicalInfo = (PhysicalInfo FAR1 *)ioreq->irData; + + /*Retrieve extended disk info*/ + /*---------------------------*/ + TFFS_API_GET_UNIT_SIZE(myIoreq, ioreq, rc, flStatus); + + /*Fill PhysicalInfo structure*/ + /*---------------------------*/ + physicalInfo->type = 0;/*docDeviceInfo.wFlashType;*/ + physicalInfo->mediaType = FL_H3; + physicalInfo->dwUnitSize = dochVol.dwVirtualUnitSizeInSectors; + physicalInfo->dwMediaSize = ((DOCH_DeviceInfo*)dochVol.intermediateBuf)->dwUnformattedCapacity; + physicalInfo->dwChipSize = physicalInfo->dwMediaSize; + physicalInfo->interleaving = 0; + + /* Return window base reg */ + /*------------------------*/ + tffsAPISetIoreq( &myIoreq,FL_GET_SOCKET_FROM_HANDLE(ioreq),0,0,0,0,0); + rc=flDOCHGetPhysicalAddress(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSGetPhysicalInfo(): DOCHGetPhysicalAddress failed with status: 0x%x "), rc)); + return (DOCH_DiskNotFound==rc) ? flAdapterNotFound : TFFS_API_RET(rc); + } + ioreq->irLength = myIoreq.irCount; + return flOK; +}/*TFFSGetPhysicalInfo()*/ + + + +#ifdef BDK_ACCESS + + +/*----------------------------------------------------------------------*/ +/* Function name : TFFSbdkReadInit*/ +/* Description : */ +/* Return type : static FLStatus */ +/* Argument : IOreq* ioreq*/ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSbdkReadInit(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + FLByte subPart; + IOreq myIoreq; + BDKStruct* bdkStrct = (BDKStruct*)(ioreq->irData); + DOCH_PartitionUserAttrWithBinary* pPartitionUserAttrWithBinary = (DOCH_PartitionUserAttrWithBinary*)dochVol.intermediateBuf; + + /* retrieve device information */ + TFFS_API_GET_UNIT_SIZE(myIoreq, ioreq, rc, flStatus); + + /*Retrieve current atttributes*/ + tffsAPISetIoreq( &myIoreq,ioreq->irHandle,0,0,dochVol.intermediateBuf,0,0); + rc = flDOCHGetParitionUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkReadInit(): flDOCHGetParitionUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + + for(subPart=0; + subPart < pPartitionUserAttrWithBinary->binPartHeader.bNumOfSubPartitions; + subPart++) + { + if (tffscmp(pPartitionUserAttrWithBinary->binPartHeader.subPartitions[subPart].bSignature, + bdkStrct->oldSign, BDK_SIGNATURE_NAME) == 0) + break; + } + if(subPart >= pPartitionUserAttrWithBinary->binPartHeader.bNumOfSubPartitions) + { /*If oldSign was not found on the partition - return error*/ + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkReadInit(): findSubPartBySignature failed with status: 0x%x "), rc)); + return flPartitionNotFound; + } + if( ((bdkStrct->length >>DOCH_SECTOR_SIZE_BITS) + (bdkStrct->startingBlock * dochVol.dwVirtualUnitSizeInSectors)) > + pPartitionUserAttrWithBinary->binPartHeader.subPartitions[subPart].dwSize ) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSbdkReadInit(): recieved length exceeds partition size.\r\n"); + return flBadParameter; + } + /*Save operation init values for actual read operation*/ + dochVol.bdkInitValues.dwStartReadSector = bdkStrct->startingBlock * dochVol.dwVirtualUnitSizeInSectors + + pPartitionUserAttrWithBinary->binPartHeader.subPartitions[subPart].dwOffset; + dochVol.bdkInitValues.dwCurrentReadByte = 0; + dochVol.bdkInitValues.dwReadLength = bdkStrct->length; + return flOK; +}/*TFFSbdkReadInit()*/ + + +/*----------------------------------------------------------------------*/ +/* Function name : TFFSbdkReadBlock*/ +/* Description : */ +/* Return type : static FLStatus */ +/* Argument : IOreq* ioreq*/ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSbdkReadBlock(IOreq* ioreq) +{ +#ifndef FL_ABS_READ_WRITE + return flFeatureNotSupported; +#else /*FL_ABS_READ_WRITE*/ + DOCH_Error dochErr = DOCH_FeatureNotSupported; + IOreq myIoreq; + BDKStruct* bdkStrct = (BDKStruct*)(ioreq->irData); + FLByte* buf = bdkStrct->bdkBuffer; + FLDword byteOffsetInSector = (dochVol.bdkInitValues.dwCurrentReadByte % DOCH_SECTOR_SIZE); + FLDword currentSector = dochVol.bdkInitValues.dwStartReadSector + + (dochVol.bdkInitValues.dwCurrentReadByte >> DOCH_SECTOR_SIZE_BITS); + FLDword fullSectorsToRead, bytesToPad; + FLWord wBytesToCopy; + + if (byteOffsetInSector != 0) + { + wBytesToCopy = (FLWord)TFFSMIN(DOCH_SECTOR_SIZE - byteOffsetInSector, bdkStrct->length); + fullSectorsToRead = (bdkStrct->length - wBytesToCopy)>>DOCH_SECTOR_SIZE_BITS; + bytesToPad = bdkStrct->length - wBytesToCopy - (fullSectorsToRead << DOCH_SECTOR_SIZE_BITS); + } + else + { + fullSectorsToRead = bdkStrct->length >>DOCH_SECTOR_SIZE_BITS; + bytesToPad = bdkStrct->length - (fullSectorsToRead << DOCH_SECTOR_SIZE_BITS); + } + + if (dochVol.bdkInitValues.dwCurrentReadByte + bdkStrct->length > dochVol.bdkInitValues.dwReadLength) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSbdkReadBlock(): Attempted reading out of readInit aread.\r\n"); + return flBadParameter; + } + /*Read NOT from start of sector*/ + if(byteOffsetInSector != 0) + { + tffsAPISetIoreq( &myIoreq,ioreq->irHandle,0,0,dochVol.intermediateBuf,currentSector,1); + dochErr = flDOCHReadPartitionSectors(&myIoreq); + if(dochErr != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkReadBlock(): TFFSAbsRead failed with status: 0x%x "), dochErr)); + TFFS_API_RET_PART_FLSTATUS(dochErr, flReadFault); + } + wBytesToCopy = (FLWord)TFFSMIN(DOCH_SECTOR_SIZE - byteOffsetInSector, bdkStrct->length); + tffscpy(buf, &dochVol.intermediateBuf[byteOffsetInSector], wBytesToCopy); + dochVol.bdkInitValues.dwCurrentReadByte += wBytesToCopy; + byteOffsetInSector = (byteOffsetInSector + wBytesToCopy)% DOCH_SECTOR_SIZE; + buf += wBytesToCopy; + if ((byteOffsetInSector % DOCH_SECTOR_SIZE) == 0) + currentSector++; + } + + /*Read requested sectors, use init values from TFFSbdkReadInit*/ + if(fullSectorsToRead > 0) + { + tffsAPISetIoreq( &myIoreq,ioreq->irHandle,0,0,buf,currentSector,fullSectorsToRead); +#ifdef FL_DMA_CONFIG + if( (((FLDword)myIoreq.irData & 3) == 0) && (gIsDMAEnabled == DOCH_GLOBAL_BOOL_PATTERN) ) + { + myIoreq.irFlags |= DOCH_USE_DMA; + } +#endif /* FL_DMA_CONFIG */ +#ifdef FL_USE_BURST_MODE_READ + if( ((FLDword)myIoreq.irData & 3) == 0) + { + myIoreq.irFlags |= DOCH_USE_BURST; + } +#endif /* FL_USE_BURST_MODE_READ */ + dochErr = flDOCHReadPartitionSectors(&myIoreq); + if(dochErr != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkReadBlock(): TFFSAbsRead failed with status: 0x%x "), dochErr)); + TFFS_API_RET_PART_FLSTATUS(dochErr, flReadFault); + } + buf += (fullSectorsToRead<irHandle,0,0,dochVol.intermediateBuf,currentSector,1); + dochErr = flDOCHReadPartitionSectors(&myIoreq); + if(dochErr != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkReadBlock(): TFFSAbsRead failed with status: 0x%x "), dochErr)); + TFFS_API_RET_PART_FLSTATUS(dochErr, flReadFault); + } + tffscpy(buf, dochVol.intermediateBuf, bytesToPad); + dochVol.bdkInitValues.dwCurrentReadByte += bytesToPad; + } + + if(dochErr != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkReadBlock(): TFFSAbsRead failed with status: 0x%x "), dochErr)); + TFFS_API_RET_PART_FLSTATUS(dochErr, flReadFault); + } + return flOK; +#endif /*FL_ABS_READ_WRITE*/ +}/*TFFSbdkReadBlock()*/ + +#ifndef FL_READ_ONLY +/*----------------------------------------------------------------------*/ +/* Function name : TFFSbdkWriteInit*/ +/* Description : */ +/* Return type : static FLStatus */ +/* Argument : IOreq* ioreq*/ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSbdkWriteInit(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq myIoreq; + FLByte subPart; + BDKStruct* bdkStrct = (BDKStruct*)(ioreq->irData); + DOCH_PartitionUserAttrWithBinary* attrSectorPtr = (DOCH_PartitionUserAttrWithBinary*)dochVol.intermediateBuf;; + + /* retrieve the unit size and other information */ + TFFS_API_GET_UNIT_SIZE(myIoreq, ioreq, rc, flStatus); + + /*Retrieve current atttributes*/ + tffsAPISetIoreq( &myIoreq,ioreq->irHandle,0,0,dochVol.intermediateBuf,0,0); + rc = flDOCHGetParitionUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkReadInit(): flDOCHGetParitionUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + + for(subPart=0; + subPart < attrSectorPtr->binPartHeader.bNumOfSubPartitions; + subPart++) + { + if (tffscmp(attrSectorPtr->binPartHeader.subPartitions[subPart].bSignature, + bdkStrct->oldSign, BDK_SIGNATURE_NAME) == 0) + break; + } + if(subPart >= attrSectorPtr->binPartHeader.bNumOfSubPartitions) + { /*If oldSign was not found on the partition - return error*/ + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkReadInit(): findSubPartBySignature failed with status: 0x%x "), rc)); + return flPartitionNotFound; + } + + if( ((bdkStrct->length >>DOCH_SECTOR_SIZE_BITS) + (bdkStrct->startingBlock * dochVol.dwVirtualUnitSizeInSectors)) > + attrSectorPtr->binPartHeader.subPartitions[subPart].dwSize ) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSbdkWriteInit(): requested size exceeds subpartition size"); + return flBadParameter; + } + + /*Save operation init values for actual write operation*/ + dochVol.bdkInitValues.dwStartWriteSector = bdkStrct->startingBlock * dochVol.dwVirtualUnitSizeInSectors + + attrSectorPtr->binPartHeader.subPartitions[subPart].dwOffset; + dochVol.bdkInitValues.dwCurrentWriteByte = 0; + dochVol.bdkInitValues.dwWriteLength = bdkStrct->length; + dochVol.bdkInitValues.bWriteSubPartitionNum = subPart; + return flOK; +}/*TFFSbdkWriteInit()*/ + +/*----------------------------------------------------------------------*/ +/* Function name : TFFSbdkWriteBlock*/ +/* Description : */ +/* Return type : static FLStatus */ +/* Argument : IOreq* ioreq*/ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSbdkWriteBlock(IOreq* ioreq) +{ +#ifndef FL_ABS_READ_WRITE + return flFeatureNotSupported; +#else /*FL_ABS_READ_WRITE*/ + DOCH_Error rc = DOCH_OK; + IOreq myIoreq; + BDKStruct* bdkStrct = (BDKStruct*)(ioreq->irData); + DOCH_PartitionUserAttrWithBinary* attrSectorPtr; + FLByte* userBuf; + FLWord wBytesToCopy, wBytesToPad; + FLDword currentSector, byteOffsetInSector; + FLDword fullSectorsToWrite; + FLDword dwUsedSize; + + byteOffsetInSector = (dochVol.bdkInitValues.dwCurrentWriteByte % DOCH_SECTOR_SIZE); + currentSector = dochVol.bdkInitValues.dwStartWriteSector + + (dochVol.bdkInitValues.dwCurrentWriteByte >> DOCH_SECTOR_SIZE_BITS); + wBytesToCopy = (FLWord)TFFSMIN(DOCH_SECTOR_SIZE - byteOffsetInSector, bdkStrct->length); + userBuf = bdkStrct->bdkBuffer; + if (byteOffsetInSector) + { + fullSectorsToWrite = (bdkStrct->length - wBytesToCopy)>>DOCH_SECTOR_SIZE_BITS; + wBytesToPad = (FLWord)(bdkStrct->length - wBytesToCopy - (fullSectorsToWrite << DOCH_SECTOR_SIZE_BITS)); + } + else + { + fullSectorsToWrite = bdkStrct->length >>DOCH_SECTOR_SIZE_BITS; + wBytesToPad = (FLWord)(bdkStrct->length - (fullSectorsToWrite << DOCH_SECTOR_SIZE_BITS)); + } + + + /*If first sector is NOT aligned: + - Read it + - Copy contiguous data + - Write sector + ==============*/ + if(byteOffsetInSector != 0) + { + /*Read*/ + tffsAPISetIoreq( &myIoreq,ioreq->irHandle,0,0,dochVol.intermediateBuf,currentSector,1); +#ifdef FL_USE_BURST_MODE_READ + /* TODO - update myIoreq.irFlags */ +#endif /*FL_USE_BURST_MODE_READ*/ + rc = flDOCHReadPartitionSectors(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkWriteBlock(): Reading sector for padding failed with status: 0x%x "), rc)); + TFFS_API_RET_PART_FLSTATUS(rc, flWriteFault); + } + + /*Copy*/ + wBytesToCopy = (FLWord)TFFSMIN(DOCH_SECTOR_SIZE - byteOffsetInSector, bdkStrct->length); + tffscpy(dochVol.intermediateBuf + byteOffsetInSector, userBuf, wBytesToCopy); + + /*Write*/ + tffsAPISetIoreq( &myIoreq,ioreq->irHandle,0,0,dochVol.intermediateBuf,currentSector,1); + rc = flDOCHWritePartitionSectors(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkWriteBlock(): Writing sector after padding failed with status: 0x%x \r\n"), rc)); + TFFS_API_RET_PART_FLSTATUS(rc, flWriteFault); + } + userBuf += wBytesToCopy; + dochVol.bdkInitValues.dwCurrentWriteByte += wBytesToCopy; + + byteOffsetInSector = (byteOffsetInSector + wBytesToCopy)% DOCH_SECTOR_SIZE; + if (byteOffsetInSector == 0) + currentSector++; + + } + + /*Write requested sectors, use init values from TFFSbdkWriteInit*/ + if(fullSectorsToWrite > 0) + { + tffsAPISetIoreq( &myIoreq,ioreq->irHandle,0,0,userBuf,currentSector,fullSectorsToWrite); +#ifdef FL_USE_DMA_ON_WRITE /*should be changed to #ifdef FL_DMA_CONFIG*/ + if( (((FLDword)userBuf & 3) == 0) && (gIsDMAEnabled == DOCH_GLOBAL_BOOL_PATTERN) ) + { + myIoreq.irFlags |= DOCH_USE_DMA; + } +#endif /*FL_USE_DMA_ON_WRITE*/ + rc = flDOCHWritePartitionSectors(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkWriteBlock(): Writing contiguous sectors failed with status:0x%x \r\n"), rc)); + TFFS_API_RET_PART_FLSTATUS(rc, flWriteFault); + } + + userBuf += (fullSectorsToWrite<irHandle,0,0,dochVol.intermediateBuf,currentSector,1); + rc = flDOCHReadPartitionSectors(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkWriteBlock(): Reading sector for padding failed with status: 0x%x "), rc)); + TFFS_API_RET_PART_FLSTATUS(rc, flWriteFault); + } + + /*Copy*/ + tffscpy(dochVol.intermediateBuf, userBuf, wBytesToPad); + + /*Write*/ + tffsAPISetIoreq( &myIoreq,ioreq->irHandle,0,0,dochVol.intermediateBuf,currentSector,1); + rc = flDOCHWritePartitionSectors(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkWriteBlock(): Writing sector after padding failed with status: 0x%x \r\n"), rc)); + TFFS_API_RET_PART_FLSTATUS(rc, flWriteFault); + } + userBuf += wBytesToPad; + dochVol.bdkInitValues.dwCurrentWriteByte += wBytesToPad; + byteOffsetInSector = (byteOffsetInSector + wBytesToPad)% DOCH_SECTOR_SIZE; + if (byteOffsetInSector == 0) + currentSector++; + } + + /*write operation was successful, update usesize*/ + /*Retrieve current attributes*/ + tffsAPISetIoreq( &myIoreq,ioreq->irHandle,0,0,dochVol.intermediateBuf,0,0); + rc = flDOCHGetParitionUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkWriteBlock(): Getting partition attributes failed with status: 0x%x \r\n"), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + attrSectorPtr = (DOCH_PartitionUserAttrWithBinary*)dochVol.intermediateBuf; + dwUsedSize = attrSectorPtr->binPartHeader.subPartitions[dochVol.bdkInitValues.bWriteSubPartitionNum].dwUsedSize; + if ((dwUsedSize << DOCH_SECTOR_SIZE_BITS) < (FLDword)(dochVol.bdkInitValues.dwCurrentWriteByte)) + { + dwUsedSize = attrSectorPtr->binPartHeader.subPartitions[dochVol.bdkInitValues.bWriteSubPartitionNum].dwUsedSize; + dwUsedSize += fullSectorsToWrite + (wBytesToPad ? 1:0); + attrSectorPtr->binPartHeader.subPartitions[dochVol.bdkInitValues.bWriteSubPartitionNum].dwUsedSize = dwUsedSize; + + rc = flDOCHSetParitionUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkWriteBlock(): Getting partition attributes failed with status: 0x%x \r\n"), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + } + return flOK; +#endif /*FL_ABS_READ_WRITE*/ +}/*TFFSbdkWriteBlock()*/ + + +/*----------------------------------------------------------------------*/ +/* Function name : TFFSbdkErase*/ +/* Description : */ +/* Return type : static FLStatus */ +/* Argument : IOreq* ioreq*/ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSbdkErase(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq myIoreq; + BDKStruct* bdkStrct = (BDKStruct*)(ioreq->irData); + FLSNative binPartNum = FL_GET_FLASH_PARTITION_FROM_HANDLE(ioreq); + FLSNative unitsToDelete = bdkStrct->length;/*((bdkStrct->length / BDK_UNIT_SIZE) + 1);*/ + FLDword lastDeletedSector, dwSubPartOffset; + DOCH_PartitionUserAttrWithBinary* attrSectorPtr; + FLByte bSubPart; + + /*get unit size etc*/ + TFFS_API_GET_UNIT_SIZE(myIoreq, ioreq, rc, flStatus); + + /*Retrieve current atttributes*/ + tffsAPISetIoreq( &myIoreq,ioreq->irHandle,0,0,dochVol.intermediateBuf,0,0); + rc = flDOCHGetParitionUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkErase(): flDOCHGetParitionUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + + attrSectorPtr = (DOCH_PartitionUserAttrWithBinary*)dochVol.intermediateBuf; + for(bSubPart=0; + bSubPart < attrSectorPtr->binPartHeader.bNumOfSubPartitions; + bSubPart++) + { + if (tffscmp(attrSectorPtr->binPartHeader.subPartitions[bSubPart].bSignature, + bdkStrct->oldSign, BDK_SIGNATURE_NAME) == 0) + break; + } + if(bSubPart >= attrSectorPtr->binPartHeader.bNumOfSubPartitions) + { /*If oldSign was not found on the partition - return error*/ + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkErase(): findSubPartBySignature failed with status: 0x%x "), rc)); + return flPartitionNotFound; + } + + if (((bdkStrct->startingBlock + unitsToDelete) * dochVol.dwVirtualUnitSize) > + (attrSectorPtr->binPartHeader.subPartitions[bSubPart].dwSize << DOCH_SECTOR_SIZE_BITS)) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSbdkErase(): Erase requested for more than partition size. "); + return flNoSpaceInVolume; + } + + /* save the offset */ + dwSubPartOffset = attrSectorPtr->binPartHeader.subPartitions[bSubPart].dwOffset; + /* update used size */ + lastDeletedSector = ((bdkStrct->startingBlock + unitsToDelete) * dochVol.dwVirtualUnitSizeInSectors); + if(lastDeletedSector >= attrSectorPtr->binPartHeader.subPartitions[bSubPart].dwUsedSize ) + { /*Update used size only if exceeds current used size*/ + attrSectorPtr->binPartHeader.subPartitions[bSubPart].dwUsedSize = + (bdkStrct->startingBlock + dochVol.dwVirtualUnitSizeInSectors - 1) & (~(dochVol.dwVirtualUnitSizeInSectors - 1)); + + /*Set modified atttributes*/ + tffsAPISetIoreq( &myIoreq,FL_GET_SOCKET_FROM_HANDLE(ioreq) + (binPartNum << 4),0,0,dochVol.intermediateBuf,0,0); + rc = flDOCHSetParitionUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkErase(): flDOCHSetParitionUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + } + + + tffsset(&myIoreq,0,sizeof(IOreq)); + myIoreq.irHandle =ioreq->irHandle; + myIoreq.irSectorNo = (FLDword)(bdkStrct->startingBlock * dochVol.dwVirtualUnitSizeInSectors) + dwSubPartOffset; + myIoreq.irSectorCount =(FLDword)dochVol.dwVirtualUnitSizeInSectors; + rc = flDOCHWipeSectors(&myIoreq); + + + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkErase(): flDOCHWipeSectors failed with status: 0x%x "), rc)); + TFFS_API_RET_PART_FLSTATUS(rc, TFFS_API_RET(rc)); + } + + return flOK; +}/*TFFSbdkErase()*/ + +/*----------------------------------------------------------------------*/ +/* Function name : TFFSbdkCreate*/ +/* Description : */ +/* Return type : static FLStatus */ +/* Argument : IOreq* ioreq*/ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSbdkCreate(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq myIoreq; + FLByte bSubPart; + DOCH_PartitionUserAttrWithBinary* attrSectorPtr; + BDKStruct* bdkStrct = (BDKStruct*)(ioreq->irData); + FLDword reqLength; + FLByte newSPIndex; + + TFFS_API_GET_UNIT_SIZE(myIoreq, ioreq, rc, flStatus); + + /*Retrieve current atttributes*/ + tffsAPISetIoreq( &myIoreq,ioreq->irHandle,0,0,dochVol.intermediateBuf,0,0); + rc = flDOCHGetParitionUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkCreate(): flDOCHGetParitionUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + + attrSectorPtr = (DOCH_PartitionUserAttrWithBinary*)dochVol.intermediateBuf; + /*Check that this is actually a binary partition*/ + if(attrSectorPtr->bType != PARTITION_TYPE_BINARY) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSbdkCreate(): Partition is NOT Binary \r\n"); + return flBadParameter; + } + + for(bSubPart=0; + bSubPart < attrSectorPtr->binPartHeader.bNumOfSubPartitions; + bSubPart++) + { + if (tffscmp(attrSectorPtr->binPartHeader.subPartitions[bSubPart].bSignature, + bdkStrct->oldSign, BDK_SIGNATURE_NAME) == 0) + break; + } + if(bSubPart >= attrSectorPtr->binPartHeader.bNumOfSubPartitions) + { /*If oldSign was not found on the partition - return error*/ + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkCreate(): findSubPartBySignature failed with status:0x%x "), rc)); + return flPartitionNotFound; + } + + /*If new SP size equals in size - simply replace signature and return*/ + reqLength = bdkStrct->length * dochVol.dwVirtualUnitSizeInSectors; + if( reqLength == 0 ) + { + DBG_PRINT_WRN(FLZONE_API, "TFFSbdkCreate(): zero size subpartition requested "); + return flNoSpaceInVolume;/*strange errors up to legacy devices*/ + } + + /* size match exactly -> replace signature */ + if(reqLength == attrSectorPtr->binPartHeader.subPartitions[bSubPart].dwSize) + { + tffscpy(attrSectorPtr->binPartHeader.subPartitions[bSubPart].bSignature, + bdkStrct->newSign, BDK_SIGNATURE_NAME); + } + else + { + /*Check that there is enough space in the current SP*/ + /*Check that max number of SP was not exceeded*/ + if(reqLength > (attrSectorPtr->binPartHeader.subPartitions[bSubPart].dwSize << DOCH_SECTOR_SIZE_BITS)) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSbdkCreate(): No Space In Volume \r\n"); + return flNoSpaceInVolume; + } + else + { + if(attrSectorPtr->binPartHeader.bNumOfSubPartitions >= (SUB_PARTITIONS_PER_BINARY-1)) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSbdkCreate(): Too Many Binary Partitions \r\n"); + return flTooManyBinaryPartitions; + } + } + /*Assign new SP number*/ + newSPIndex = attrSectorPtr->binPartHeader.bNumOfSubPartitions; + + /*Set current and new SP atttributes*/ + attrSectorPtr->binPartHeader.subPartitions[bSubPart].dwSize -= reqLength; + /*Set new SP atttributes*/ + attrSectorPtr->binPartHeader.subPartitions[newSPIndex].dwOffset = + attrSectorPtr->binPartHeader.subPartitions[bSubPart].dwOffset + + attrSectorPtr->binPartHeader.subPartitions[bSubPart].dwSize; + attrSectorPtr->binPartHeader.subPartitions[newSPIndex].dwSize = reqLength; + + tffscpy(attrSectorPtr->binPartHeader.subPartitions[newSPIndex].bSignature, + bdkStrct->newSign, + BDK_SIGNATURE_NAME); + /*Increment number of SP by 1*/ + attrSectorPtr->binPartHeader.bNumOfSubPartitions++; + } + + /*Set modified atttributes*/ + tffsAPISetIoreq( &myIoreq,ioreq->irHandle,0,0,dochVol.intermediateBuf,0,0); + rc = flDOCHSetParitionUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkCreate(): flDOCHSetParitionUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + return flOK; +}/*TFFSbdkCreate()*/ + + +#endif /*FL_READ_ONLY*/ + +/*----------------------------------------------------------------------*/ +/* Function name : TFFSbdkPartitionInfo*/ +/* Description : */ +/* Return type : static FLStatus */ +/* Argument : IOreq* ioreq*/ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSbdkPartitionInfo(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq myIoreq; + DOCH_PartitionUserAttrWithBinary* attrSectorPtr; + BDKStruct* bdkStrct = (BDKStruct*)(ioreq->irData); + FLDword dwPartititonSize, dwUsedUnits; + /*If oldSign was not found on the partition - return error*/ + FLByte bSubPart; + + TFFS_API_GET_UNIT_SIZE(myIoreq, ioreq, rc, flStatus); + + if( FL_GET_FLASH_PARTITION_FROM_HANDLE(ioreq) >= (dochVol.numOfBinaryPartitions+dochVol.otpExists+dochVol.iplExists) ) + { + return flBadDriveHandle; + } + + bdkStrct->flags = dochVol.numOfBinaryPartitions; /*total number of BDK on the media*/ + + tffsAPISetIoreq( &myIoreq, ioreq->irHandle, 0,0,dochVol.intermediateBuf,0,0); + rc = flDOCHPartitionInfo(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkPartitionInfo(): flDOCHGetParitionUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + dwPartititonSize = ((DOCH_PartitionInfo*)dochVol.intermediateBuf)->nPartitionSize << DOCH_SECTOR_SIZE_BITS; + + /*Retrieve current atttributes*/ + tffsAPISetIoreq( &myIoreq, ioreq->irHandle, 0,0,dochVol.intermediateBuf,0,0); + rc = flDOCHGetParitionUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkPartitionInfo(): flDOCHGetParitionUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + + attrSectorPtr = (DOCH_PartitionUserAttrWithBinary*)dochVol.intermediateBuf; + /*Check that this is actually a binary partition*/ + if(attrSectorPtr->bType != PARTITION_TYPE_BINARY) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSbdkPartitionInfo(): Partition is NOT Binary \r\n"); + return flBadParameter; + } + + for(bSubPart=0; + bSubPart < attrSectorPtr->binPartHeader.bNumOfSubPartitions; + bSubPart++) + { + if (tffscmp(attrSectorPtr->binPartHeader.subPartitions[bSubPart].bSignature, + bdkStrct->oldSign, BDK_SIGNATURE_NAME) == 0) + break; + } + if(bSubPart >= attrSectorPtr->binPartHeader.bNumOfSubPartitions) + { /*If oldSign was not found on the partition - return error*/ + DBG_PRINT_ERR(FLZONE_API, "TFFSbdkPartitionInfo(): Sub partition not found."); + return flNoSpaceInVolume ; /* for compatibility with legacy devices */ + } + + /*Returned values*/ + dwUsedUnits = ((attrSectorPtr->binPartHeader.subPartitions[bSubPart].dwUsedSize + dochVol.dwVirtualUnitSizeInSectors - 1)/ dochVol.dwVirtualUnitSizeInSectors); + bdkStrct->length = dwUsedUnits * dochVol.dwVirtualUnitSize; + if(bdkStrct->length == 0) /*Used size must be at least 1 unit*/ + bdkStrct->length = dochVol.dwVirtualUnitSizeInSectors << DOCH_SECTOR_SIZE_BITS; + + bdkStrct->startingBlock = attrSectorPtr->binPartHeader.subPartitions[bSubPart].dwSize << DOCH_SECTOR_SIZE_BITS; + ioreq->irLength = dwPartititonSize; + + return flOK; +}/*TFFSbdkPartitionInfo()*/ +#endif /*BDK_ACCESS*/ + +/*----------------------------------------------------------------------*/ +/* f l I n s e r t P r o t e c t i o n K e y */ +/* b d k I n s e r t P r o t e c t i o n K e y */ +/* */ +/* Insert the protection key in order to remove the protection of the */ +/* partition specified by the drive handle */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based), doch count */ +/* bits 3-0 - Socket # (zero based) */ +/* irData : pointer to an 8 bytes key array */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSInsertProtectionKey(IOreq* ioreq) +{ + IOreq myIoreq; + FLByte bPartNum; + FLStatus flStatus; + + /* Format DOCH_PartitionAcessPassword structure */ + /* Note that legacy devices has only 8 bytes passkey */ + /*-----------------------------------------------*/ + bPartNum = FL_GET_FLASH_PARTITION_FROM_HANDLE(ioreq); + flStatus = tffsApiAuthPartition(&myIoreq, ioreq, bPartNum, (FLByte *)ioreq->irData, PROTECTION_KEY_LENGTH ); + if( flStatus == flNotProtected ) + flStatus = flOK; + + return flStatus; +}/*TFFSInsertProtectionKey()*/ + +#ifdef BDK_ACCESS + +#endif /* BDK_ACCESS */ + +#ifdef HW_OTP +/*----------------------------------------------------------------------*/ +/* f l O T P S i z e */ +/* */ +/* Get the OTP size and state */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* bits 3-0 - Socket # (zero based) */ +/* irLength : The size of the used OTP area in bytes */ +/* irCount : The size of the OTP area in bytes */ +/* irFlags : LOCKED_OTP for a locked area otherwise unlocked */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSOTPSize(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq myIoreq; + + /*Get partition (OTP) info*/ + /*----------------------*/ + tffsAPISetIoreq( &myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq) + (TFFS_API_OTP_PARTITION_NUM << 4), + 0,0,dochVol.intermediateBuf,0,0); + rc = flDOCHPartitionInfo(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSOTPSize(): flDOCHPartitionInfo failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + /*Returned values*/ + ioreq->irCount = TFFS_API_OTP_PART_SIZE; + ioreq->irFlags = ((((DOCH_PartitionInfo*)dochVol.intermediateBuf)->dwCommandFlagsOrStatuses & DOCH_CFSB_PERM_LOCKED) == DOCH_CFSB_PERM_LOCKED); + if (ioreq->irFlags) + ioreq->irLength = TFFS_API_OTP_PART_SIZE; + else + ioreq->irLength = 0; + return flOK; +}/*TFFSOTPSize()*/ + +/*----------------------------------------------------------------------*/ +/* f l O T P R e a d */ +/* */ +/* Read OTP Partition */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irData : Address of user buffer to read into */ +/* irCount : First byte to read. */ +/* irLength : Number of consecutive bytes to read */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSOTPRead(IOreq* ioreq) +{ +#ifndef FL_ABS_READ_WRITE + return flFeatureNotSupported; +#else /*FL_ABS_READ_WRITE*/ + FLStatus status = flReadFault; + IOreq myIoreq; + /*FLByte padSector[DOCH_SECTOR_SIZE];*/ + FLByte * padSector = dochVol.intermediateBuf; + FLByte* buf = (FLByte*)ioreq->irData; + FLDword firstByteInFirstSector = (ioreq->irCount % DOCH_SECTOR_SIZE); + FLDword firstSector = (ioreq->irCount >> DOCH_SECTOR_SIZE_BITS); + FLDword bytesToRead = ioreq->irLength; + /* FLBoolean lessThenOneSector = FALSE; */ + FLDword padBytesInFirstSector, bytesInUnfullSector,fullSectorsToRead,bytesToPad; + + if((firstByteInFirstSector + bytesToRead) < DOCH_SECTOR_SIZE) + { + /* lessThenOneSector = TRUE; */ + padBytesInFirstSector = (DOCH_SECTOR_SIZE - (firstByteInFirstSector + bytesToRead)); + if(firstByteInFirstSector == 0) + bytesInUnfullSector = bytesToRead; + else + bytesInUnfullSector = 0; + fullSectorsToRead = 0; + bytesToPad = padBytesInFirstSector; + } + else + { + padBytesInFirstSector = (firstByteInFirstSector == 0) ? 0 : (DOCH_SECTOR_SIZE - firstByteInFirstSector); + bytesInUnfullSector = ((ioreq->irLength - padBytesInFirstSector) % DOCH_SECTOR_SIZE); + fullSectorsToRead = ((ioreq->irLength - (padBytesInFirstSector + bytesInUnfullSector))>>DOCH_SECTOR_SIZE_BITS); + bytesToPad = (bytesInUnfullSector == 0) ? 0 : (DOCH_SECTOR_SIZE - bytesInUnfullSector); + } + + /*Read NOT from start of sector*/ + if(firstByteInFirstSector != 0) + { + tffsset(padSector, 0, sizeof(padSector)); + tffsAPISetIoreq( &myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq) + (TFFS_API_OTP_PARTITION_NUM << 4), + 0,0,padSector,firstSector,1); + status = TFFSAbsRead(&myIoreq, &(ioreq->irSectorCount)); + if(status != flOK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSOTPRead(): TFFSAbsRead failed with status: 0x%x "), status)); + return status; + } + tffscpy(buf, &padSector[firstByteInFirstSector], (DOCH_SECTOR_SIZE - firstByteInFirstSector)); + buf += (DOCH_SECTOR_SIZE - firstByteInFirstSector); + firstSector++; + } + + if(fullSectorsToRead > 0) + { + tffsAPISetIoreq(&myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq) + (TFFS_API_OTP_PARTITION_NUM << 4), + 0,0,buf,firstSector,fullSectorsToRead); + status = TFFSAbsRead(&myIoreq, &(ioreq->irSectorCount)); + if(status != flOK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSOTPRead(): TFFSAbsRead failed with status: 0x%x "), status)); + return status; + } + buf += (fullSectorsToRead<irSectorCount)); + if(status != flOK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSOTPRead(): TFFSAbsRead failed with status: 0x%x "), status)); + return status; + } + tffscpy(buf, padSector, bytesInUnfullSector); + } + return flOK; +#endif /*FL_ABS_READ_WRITE*/ +}/*TFFSOTPRead()*/ + +/*----------------------------------------------------------------------*/ +/* f l O T P W r i t e A n d L o c k */ +/* */ +/* Write data to OTP partition and lock the partition */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* irData : pointer to user data */ +/* irLength : The size to write, in bytes. */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSOTPWriteAndLock(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq myIoreq; + + tffsAPISetIoreq(&myIoreq,FL_GET_SOCKET_FROM_HANDLE(ioreq) + (TFFS_API_OTP_PARTITION_NUM << 4),0, + 0,ioreq->irData,0,(ioreq->irLength>>DOCH_SECTOR_SIZE_BITS)); + + /*1. Perform last write + 2. Lock the partition for writing (OTP) + ---------------------------------------*/ + rc = flDOCHWriteAndLock(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSOTPWriteAndLock(): flDOCHWriteAndLock failed with status: 0x%x "), rc)); + TFFS_API_RET_PART_FLSTATUS(rc, flWriteFault); + } + return flOK; +}/*TFFSOTPWriteAndLock()*/ + + +/*----------------------------------------------------------------------*/ +/* f l G e t U n i q u e I D */ +/* */ +/* Returns the 16 bytes device unique ID */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* irData : pointer to a 16 bytes buffer to read into the */ +/* unique ID data */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/* irData : 16 bytes unique ID buffer */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSGetUniqueID(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_GeneralFailure; + IOreq myIoreq; + + tffsAPISetIoreq(&myIoreq,FL_GET_SOCKET_FROM_HANDLE(ioreq),0,0,dochVol.intermediateBuf,0,0); + + /*Get extended disk info*/ + /*----------------------*/ + rc = flDOCHIdentifyDiskOnChipDevice(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSGetUniqueID(): flDOCHIdentifyDiskOnChipDevice failed with status: 0x%x "), rc)); + return (rc==DOCH_DiskNotFound)? flUnknownMedia : TFFS_API_RET(rc); + } + + tffscpy(ioreq->irData, ((DOCH_DeviceInfo*)dochVol.intermediateBuf)->bUniqueID, + sizeof(((DOCH_DeviceInfo*)dochVol.intermediateBuf)->bUniqueID)); + return flOK; +}/*TFFSGetUniqueID()*/ + +/*----------------------------------------------------------------------*/ +/* f l G e t C u s t o m e r I D */ +/* */ +/* Returns the 4 bytes customer ID */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* irData : pointer to a 4 bytes buffer to read into the */ +/* customer ID */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/* irData : 4 bytes unique ID buffer */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSGetCustomerID(IOreq* ioreq) +{ + FLStatus status; + IOreq tmpIoreq; + FLByte uniqueID[16]; + + /*Use local copy of ioreq*/ + /*-----------------------*/ + tffsAPISetIoreq(&tmpIoreq,ioreq->irHandle,0,0,uniqueID,0,0); + + /*Retrieve UniqueID*/ + /*-----------------*/ + status = TFFSGetUniqueID(&tmpIoreq); + if(status != flOK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSGetCustomerID(): TFFSGetUniqueID failed with status: 0x%x "), status)); + return status; + } + + /*Extract 1st 4 bytes (CustomerID)*/ + /*--------------------------------*/ + tffscpy(ioreq->irData, uniqueID, 8); + return flOK; +}/*TFFSGetCustomerID()*/ + +#endif /* HW_OTP */ + + + +/*----------------------------------------------------------------------*/ +/* f l R e c o v e r F r o m P o w e r L o s s */ +/* */ +/* Recover from a power OFF without full TrueFFS initialization. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* */ +/* Returns: None */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSRecoverFromPowerLoss(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq myIoreq; + + tffsAPISetIoreq(&myIoreq,FL_GET_SOCKET_FROM_HANDLE(ioreq),0,0,0,0,0); + rc = flDOCHRecoverFromPowerLoss(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSRecoverFromPowerLoss(): flDOCHRecoverFromPowerLoss failed with status: 0x%x "), rc)); + return flBadParameter; + } + return flOK; +}/*TFFSRecoverFromPowerLoss()*/ + + +/*----------------------------------------------------------------------*/ +/* f l D e e p P o w e r D o w n M o d e */ +/* */ +/* Forces the device into and out of the deep power down mode */ +/* To set the Auto-DPD, ACTIVE/INACTIVE modes and timeout MUST be reset,*/ +/* by other API! */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* irFlags : DEEP_POWER_DOWN forces the low power consumption */ +/* mode. otherwise turning to the regular mode */ +/* */ +/* Returns: None */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSDeepPowerDownMode(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq myIoreq; + + tffsAPISetIoreq( &myIoreq,FL_GET_SOCKET_FROM_HANDLE(ioreq),0,0,0,gDpdSettings.timeOut, + (gDpdSettings.activeMode | gDpdSettings.inActiveMode) ); + if (ioreq->irFlags == DEEP_POWER_DOWN) /* enter DPD */ + { + /* reset modes + leave in inactive mode */ + myIoreq.irFlags = DOCH_PM_INACTIVE_MODE | DOCH_PM_SET_BOTH_MODES; + } + else/* exit DPD*/ + { + if( TFFS_API_IS_AUTO_DPD_ON(FL_GET_SOCKET_FROM_HANDLE(ioreq)) ) /* AutoDPD on */ + { + myIoreq.irFlags = DOCH_PM_INACTIVE_MODE | DOCH_PM_SET_BOTH_MODES; /* MUST be in inactive to allow all AutoDPDs*/ + } + else /* AutoDPD off*/ + { + myIoreq.irFlags = DOCH_PM_WORK_MODE | DOCH_PM_SET_BOTH_MODES;/* just put in active mode */ + } + } + + rc = DOCHSetPowerMode(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSDeepPowerDownMode(): DOCHSetPowerMode failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return TFFS_API_RET(rc); + } + return flOK; +}/*TFFSDeepPowerDownMode()*/ + +/*----------------------------------------------------------------------*/ +/* f l H w C o n f i g */ +/* */ +/* his routine enables to control DiskOnChip H/W features. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* irFlags : Describing H/W configuration Type */ +/* irLength : New value to use - Different for each H/W */ +/* configuration type chosen. */ +/* */ +/* Returns: None */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSHwConfig(IOreq* ioreq) +{ + IOreq myIoreq; + DOCH_Error dochRC; + FLDword ctrl; + + switch(ioreq->irFlags) + { + case FL_DPD_TYPE:/*Configures the behavior of DiskOnChip DPD input pin*/ + tffsAPISetIoreq(&myIoreq,ioreq->irHandle,DOCH_POWER_DOWN,0,0,0,0); + switch(ioreq->irLength) + { + case FL_DPD_DISABLED: + myIoreq.irLength |= DOCH_DPD_PIN_DISABLED; + break; + + case FL_DPD_EXIT_RISE_EDGE: + myIoreq.irLength |= (DOCH_DPD_PIN_ENABLED | DOCH_DPD_PIN_POL_HIGH); + break; + + case FL_DPD_EXIT_FALL_EDGE: + myIoreq.irLength |= (DOCH_DPD_PIN_ENABLED | DOCH_DPD_PIN_POL_LOW); + break; + + case FL_DPD_ENTER_1_EXIT_0: + case FL_DPD_ENTER_0_EXIT_1: + default: + return flFeatureNotSupported; + } + + dochRC = DOCHConfigHW(&myIoreq); + if(dochRC != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSHwConfig(): flDOCHDPDMode failed...\r\n"); + return flBadFunction; + } + + break; + + case FL_PAGE_MODE_TYPE: + case FL_TURBO_MODE_TYPE: + case FL_DPS_2_COPIES_TYPE: + return flOK; + + case FL_IRQ_RB_TYPE : + /* Enable interrupts (if requested) */ + if(ioreq->irLength & FL_IRQ_EDGE_TYPE)/* Not supported in H3 */ + { + DBG_PRINT_WRN(FLZONE_API, "TFFSHwConfig(): EDGE interrupts not supported by mDOC H3 devices, LEVEL interrupt enabled.\r\n"); + } + /* save set configuration */ + gDochIrqEnabled[ioreq->irHandle] = (ioreq->irLength & FL_INT_RB_ENABLED); + break; + + case FL_DMA_TYPE: + tffsAPISetIoreq(&myIoreq,ioreq->irHandle,DOCH_DMA_ENABLE,0,0,0,0); + if (ioreq->irLength & FL_DMA_HW_ENABLED) + { + myIoreq.irLength = TRUE; + } + else + { + myIoreq.irLength = FALSE; + } + dochRC = DOCHConfigHW(&myIoreq); + if(dochRC != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSHwConfig(): Setting DMA enable status failed.\r\n"); + return (dochRC==DOCH_BadParameter) ? flBadParameter : flFeatureNotSupported; + } + ctrl = ((DOCH_DMA_PULSE_WIDTH)<<4) | DOCH_DMA_REQ_POL_LOW; + if (ioreq->irLength & FL_DMA_REQ_EDGE) + ctrl |= DOCH_DMA_REQ_EDGE; + if (ioreq->irLength & FL_NEGATED_0_ASSERTED_1) + ctrl &= ~DOCH_DMA_REQ_POL_LOW; + tffsAPISetIoreq(&myIoreq,ioreq->irHandle,DOCH_DMA_CTRL,0,0,ctrl, 0); + dochRC = DOCHConfigHW(&myIoreq); + if(dochRC != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSHwConfig(): Setting DMA enable status failed.\r\n"); + return (dochRC==DOCH_BadParameter) ? flBadParameter : flFeatureNotSupported; + } + break; + default: + DBG_PRINT_ERR(FLZONE_API, "TFFSHwConfig(): Not Supported \r\n"); + return flFeatureNotSupported; + } + + return flOK; +}/*TFFSHwConfig*/ + +#ifndef NO_IPL_CODE +/*----------------------------------------------------------------------*/ +/* f l W r i t e I P L */ +/* */ +/* Place a user buffer to both copies of the IPL area */ +/* */ +/* Note : */ +/* */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (0,1,..) */ +/* 4 LSB - Socket number */ +/* irData : Pointer to user buffer */ +/* irLength : Size of the buffer */ +/* irFlags : See flags bellow */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSWriteIPL(IOreq* ioreq) +{ +#ifdef FL_READ_ONLY + return flFeatureNotSupported; +#else /*FL_READ_ONLY*/ + DOCH_Error rc = DOCH_GeneralFailure; + IOreq ioreq_WriteIpl; + IOreq ioreq_ReadIpl; + FLDword iplFlags, totalIPLSize, i , dwIPLSizeToWrite=0; + + if ((ioreq->irLength & (DOCH_SECTOR_SIZE - 1)) != 0) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSWriteIPL(): writeIPL must be done in buffers with N x 512B size (while n is a positive integer.\r\n"); + return flBadParameter; + } + if ((ioreq->irFlags & FL_IPL_128K_WINDOW_MODE) == 0) /*8KB window*/ + { + iplFlags = DOCH_IPL_MODE_8KB_WINDOW | DOCH_IPL_MODE_ADDRESS_SHIFT_IN_AFFECT; + if (ioreq->irFlags & FL_IPL_VIRTUAL_RAM_MODE) + { + iplFlags |= DOCH_IPL_MODE_VIRTUAL_RAM; + totalIPLSize = TFFS_API_VIRTUAL_RAM_8K_IPL_SIZE; + } + else if (ioreq->irFlags & FL_DOC_IPL_PAGED_RAM_MODE) + { + iplFlags |= DOCH_IPL_MODE_PAGED_RAM; + totalIPLSize = TFFS_API_PAGED_IPL_SIZE; + } + else + { + totalIPLSize = TFFS_API_8K_NORMAL_IPL_SIZE; + } + } + else /*128KB window*/ + { + iplFlags = DOCH_IPL_MODE_NORMAL_RAM | DOCH_IPL_MODE_ADDRESS_SHIFT_IN_AFFECT; + if (ioreq->irFlags & FL_IPL_VIRTUAL_RAM_MODE) + { + iplFlags |= DOCH_IPL_MODE_VIRTUAL_RAM; + totalIPLSize = TFFS_API_VIRTUAL_RAM_128K_IPL_SIZE; + } + else if (ioreq->irFlags & FL_DOC_IPL_PAGED_RAM_MODE) + { + iplFlags |= DOCH_IPL_MODE_PAGED_RAM; + totalIPLSize = TFFS_API_PAGED_IPL_SIZE; + } + else + { + totalIPLSize = TFFS_API_128K_NORMAL_IPL_SIZE; + } + } + if (ioreq->irFlags & FL_IPL_SWAP_BYTES_MODE) + { + iplFlags |= DOCH_IPL_MODE_ACTIVE_SWAP_BYTES; + } + if ((FLDword)(ioreq->irCount + ((ioreq->irLength) >> DOCH_SECTOR_SIZE_BITS)) > totalIPLSize) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSWriteIPL(): IPL size exceed current IPL mode allowed size."); + return flBadParameter; + } + if (iplFlags & DOCH_IPL_MODE_VIRTUAL_RAM) + { + /*virtual mode requires all IPL size to be written*/ + dwIPLSizeToWrite = totalIPLSize; + } + else + { + dwIPLSizeToWrite = (FLDword)(ioreq->irCount + ((ioreq->irLength) >> DOCH_SECTOR_SIZE_BITS)); + /*round to page size*/ + dwIPLSizeToWrite= (dwIPLSizeToWrite+DOCH_SECTORS_PER_PAGE-1) & (~(DOCH_SECTORS_PER_PAGE-1)); + if (dwIPLSizeToWrite > totalIPLSize) /*sanity check - should not fail*/ + { + DBG_PRINT_ERR(FLZONE_API, "TFFSWriteIPL(): IPL size exceed current IPL mode allowed size."); + return flBadParameter; + } + } + if (ioreq->irCount != 0) + { + for (i = 0; i < (FLDword)(ioreq->irCount);i++) + { + tffsAPISetIoreq(&ioreq_ReadIpl, FL_GET_SOCKET_FROM_HANDLE(ioreq),iplFlags,0,dochVol.intermediateBuf,1,i); + rc = flDOCHReadIPL(&ioreq_ReadIpl); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSWriteIPL(): Failed reading previous IPL copy. status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + TFFS_API_RET_PART_FLSTATUS(rc, flReadFault); + } + + tffsAPISetIoreq(&ioreq_WriteIpl, FL_GET_SOCKET_FROM_HANDLE(ioreq),iplFlags,0,dochVol.intermediateBuf, + 1, dwIPLSizeToWrite); + if (i == 0) + ioreq_WriteIpl.irFlags |= DOCH_IPL_WRITE_FIRST_CHUNK; + rc = flDOCHWriteIPL(&ioreq_WriteIpl); + if (rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSWriteIPL(): Failed writing previous IPL copy. status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + TFFS_API_RET_PART_FLSTATUS(rc, flWriteFault); + } + } + } + + tffsAPISetIoreq(&ioreq_WriteIpl, FL_GET_SOCKET_FROM_HANDLE(ioreq),iplFlags,0,ioreq->irData, + ioreq->irLength >> DOCH_SECTOR_SIZE_BITS, dwIPLSizeToWrite); + if (ioreq->irCount == 0) + { + ioreq_WriteIpl.irFlags |= DOCH_IPL_WRITE_FIRST_CHUNK; + + ioreq_WriteIpl.irFlags |= (FL_IPL_DELAY_CELL_CONFIG_READ<<4); + ioreq_WriteIpl.irFlags |= (FL_IPL_DELAY_CELL_CONFIG_WRITE<<8); + } + + rc = flDOCHWriteIPL(&ioreq_WriteIpl); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSWriteIPL(): Failed writing new IPL data. status: "); + DBG_PRINT_ERR(FLZONE_API, "TFFSWriteIPL(): TFFSAbsWrite failed with status: "); + TFFS_API_RET_PART_FLSTATUS(rc, flWriteFault); + } + + /*Write remainder*/ + tffsset(dochVol.intermediateBuf, 0, DOCH_SECTOR_SIZE); + for (i = ((ioreq->irLength >> DOCH_SECTOR_SIZE_BITS)+ ioreq->irCount); i < dwIPLSizeToWrite ; i++) + { + rc = flDOCHWriteIPL(tffsAPISetIoreq( &ioreq_WriteIpl,FL_GET_SOCKET_FROM_HANDLE(ioreq),iplFlags, + 0,dochVol.intermediateBuf,1,totalIPLSize)); + if (rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSWriteIPL(): Failed writing previous IPL copy. status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + TFFS_API_RET_PART_FLSTATUS(rc, flWriteFault); + } + } + return flOK; +#endif /*FL_READ_ONLY*/ +}/*TFFSWriteIPL*/ + +/*----------------------------------------------------------------------*/ +/* r e a d I P L */ +/* */ +/* Read IPL to user buffer. */ +/* */ +/* Note : Read length must be a multiplication of 512 bytes */ +/* Note : Causes DiskOnChip Millennium Plus to download (i,e protection */ +/* key will be removed from all partitions. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (0,1,..) */ +/* 4 LSB - Socket number */ +/* irData : Pointer to user buffer */ +/* irLength : Size of the buffer */ +/* irCount : Used IPL size on the media */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSReadIPL(IOreq* ioreq) +{ + FLStatus rc = flReadFault; + DOCH_Error dochErr = DOCH_ReadFault; + FLDword fullSectorsToRead, bytesToPad = 0; + /*FLByte padBuffer[DOCH_SECTOR_SIZE];*/ + FLByte * padBuffer=dochVol.intermediateBuf; + IOreq ioreq_ipl; + + fullSectorsToRead = ioreq->irLength >> DOCH_SECTOR_SIZE_BITS; + bytesToPad = ioreq->irLength % DOCH_SECTOR_SIZE; + tffsset(&ioreq_ipl, 0, sizeof(ioreq_ipl)); + ioreq_ipl.irHandle = FL_GET_SOCKET_FROM_HANDLE(ioreq); + ioreq_ipl.irCount = ioreq->irCount; + + if (fullSectorsToRead > 0) + { + ioreq_ipl.irLength = fullSectorsToRead; + ioreq_ipl.irData = ioreq->irData; + dochErr = flDOCHReadIPL(&ioreq_ipl); + if(dochErr != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSReadIPL(): TFFSAbsRead failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), dochErr)); + TFFS_API_RET_PART_FLSTATUS(rc, flReadFault); + } + } + + if ((bytesToPad > 0) || (ioreq->irLength == 0)) + { + ioreq_ipl.irLength = 1; + ioreq_ipl.irData = padBuffer; + dochErr = flDOCHReadIPL(&ioreq_ipl); + if(dochErr != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSReadIPL(): TFFSAbsRead failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), dochErr)); + TFFS_API_RET_PART_FLSTATUS(rc, flReadFault); + } + tffscpy((void*)(((FLByte*)ioreq->irData) + (fullSectorsToRead<irFlags = DOCH_IPL_MODE_NORMAL_RAM; + if ((ioreq_ipl.irFlags & DOCH_IPL_MODE_PAGED_RAM) != 0) + ioreq->irFlags |= FL_DOC_IPL_PAGED_RAM_MODE; + if ((ioreq_ipl.irFlags & DOCH_IPL_MODE_VIRTUAL_RAM) != 0) + ioreq->irFlags |= FL_IPL_VIRTUAL_RAM_MODE; + if ((ioreq_ipl.irFlags & DOCH_IPL_MODE_ADDRESS_SHIFT_IN_AFFECT) == 0) + ioreq->irFlags |= FL_IPL_NO_ADDRESS_SHIFT_MODE; + if ((ioreq_ipl.irFlags & DOCH_IPL_MODE_ACTIVE_SWAP_BYTES) != 0) + ioreq->irFlags |= FL_IPL_SWAP_BYTES_MODE; + if ((ioreq_ipl.irFlags & DOCH_IPL_MODE_8KB_WINDOW) == 0) + { + ioreq->irFlags |= FL_IPL_128K_WINDOW_MODE; + if ((ioreq_ipl.irFlags & DOCH_IPL_MODE_VIRTUAL_RAM) != 0) + ioreq->irCount = TFFS_API_VIRTUAL_RAM_128K_IPL_SIZE << DOCH_SECTOR_SIZE_BITS; + else if ((ioreq_ipl.irFlags & DOCH_IPL_MODE_PAGED_RAM) != 0) + ioreq->irCount = (TFFS_API_PAGED_IPL_SIZE << DOCH_SECTOR_SIZE_BITS); + else + ioreq->irCount = (TFFS_API_128K_NORMAL_IPL_SIZE << DOCH_SECTOR_SIZE_BITS); + } + else + { + if ((ioreq_ipl.irFlags & DOCH_IPL_MODE_VIRTUAL_RAM) != 0) + ioreq->irCount = TFFS_API_VIRTUAL_RAM_8K_IPL_SIZE << DOCH_SECTOR_SIZE_BITS; + else if ((ioreq_ipl.irFlags & DOCH_IPL_MODE_PAGED_RAM) != 0) + ioreq->irCount = (TFFS_API_PAGED_IPL_SIZE << DOCH_SECTOR_SIZE_BITS); + else + ioreq->irCount = (TFFS_API_8K_NORMAL_IPL_SIZE << DOCH_SECTOR_SIZE_BITS); + } + return flOK; +}/*TFFSReadIPL()*/ + +#endif /*NO_IPL_CODE*/ + + +/*----------------------------------------------------------------------*/ +/* f l I d e n t i f y P r o t e c t i o n */ +/* b d k I d e n t i f y P r o t e c t i o n */ +/* */ +/* Returns the specified partitions protection attributes */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/* irFlags CHANGEABLE_PROTECTION - changeable protection type */ +/* PROTECTABLE - partition can receive protection */ +/* READ_PROTECTED - partition is read protected */ +/* WRITE_PROTECTED - partition is write protected */ +/* LOCK_ENABLED - HW lock signal is enabled */ +/* LOCK_ASSERTED - HW lock signal is asserted */ +/* KEY_INSERTED - key is inserted (not currently */ +/* protected. */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSIdentifyProtection(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq myIoreq; + FLByte protectionType,guestAccessMode,lockControl,otpBit,hwLockSignal,sLockSignal,authenticated; +#ifdef FL_SOTP + FLByte sotp; + FLDword dwSOTPoffset=0; +#endif /*FL_SOTP*/ + + /*Retrieve partition info*/ + /*-----------------------*/ + rc = flDOCHPartitionInfo(tffsAPISetIoreq(&myIoreq,ioreq->irHandle,0,0,dochVol.intermediateBuf,0,0)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSIdentifyProtection(): flDOCHPartitionInfo failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + + protectionType = (FLByte)(((DOCH_PartitionInfo*)dochVol.intermediateBuf)->partitionAttributes2 & DOCH_PA2B_PROTECTION_TYPE); + guestAccessMode = (FLByte)((((DOCH_PartitionInfo*)dochVol.intermediateBuf)->partitionAttributes2 & DOCH_PA2B_GUEST_MODE) + >> DOCH_PA2O_GUEST_MODE); + lockControl = (FLByte)((((DOCH_PartitionInfo*)dochVol.intermediateBuf)->partitionAttributes2 & DOCH_PA2B_LOCK_CTRL) + >> DOCH_PA2O_LOCK_CTRL); + otpBit = (FLByte)((((DOCH_PartitionInfo*)dochVol.intermediateBuf)->dwCommandFlagsOrStatuses & DOCH_CFSB_PERM_LOCKED) + >> DOCH_CFSO_PERM_LOCKED); + + hwLockSignal = (FLByte)((((DOCH_PartitionInfo*)dochVol.intermediateBuf)->dwCommandFlagsOrStatuses & DOCH_CFSB_HW_LOCK_ASSERTED) + >> DOCH_CFSO_HW_LOCK_ASSERTED); + sLockSignal = (FLByte)((((DOCH_PartitionInfo*)dochVol.intermediateBuf)->dwCommandFlagsOrStatuses & DOCH_CFSB_SW_LOCK_ASSERTED) + >> DOCH_CFSO_SW_LOCK_ASSERTED); + + authenticated = (FLByte)((((DOCH_PartitionInfo*)dochVol.intermediateBuf)->dwCommandFlagsOrStatuses & DOCH_CFSB_USER_AUTHENTICATED) + >> DOCH_CFSO_USER_AUTHENTICATED); +#ifdef FL_SOTP + sotp = (FLByte)((((DOCH_PartitionInfo*)dochVol.intermediateBuf)->dwCommandFlagsOrStatuses & DOCH_CFSB_SOTP_LOCKED) + >> DOCH_CFSO_SOTP_LOCKED); + if (sotp) + { + /*return SOTP offset*/ + ioreq->irCount=((DOCH_PartitionInfo*)dochVol.intermediateBuf)->dwSOTPoffset; + } + else + { + /*illegal offset returned in case of non SOTP partition*/ + ioreq->irCount=0xFFFFFFFF; + } +#endif /*FL_SOTP*/ + + /*Retrieve partition attributes*/ + /*-----------------------------*/ + tffsset(dochVol.intermediateBuf, 0, sizeof(DOCH_PartitionUserAttrWithBinary)); + rc = flDOCHGetParitionUserAttributes(tffsAPISetIoreq(&myIoreq,ioreq->irHandle,0,0,dochVol.intermediateBuf,0,0 )); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSIdentifyProtection(): flDOCHGetParitionUserAttributes failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + /*Set popper bits in irFlags according to partition attributes*/ + /*------------------------------------------------------------*/ + ioreq->irFlags=0; + + /*Set PROTECTABLE and CHANGEABLE_PROTECTION to user attributes*/ + /*------------------------------------------------------------*/ + ioreq->irFlags |= (((DOCH_PartitionUserAttrWithBinary*)dochVol.intermediateBuf)->bProtected * PROTECTABLE); + ioreq->irFlags |= (((DOCH_PartitionUserAttrWithBinary*)dochVol.intermediateBuf)->bChangableProtection * CHANGEABLE_PROTECTION); + + if(protectionType != DOCH_PARTITION_NOT_PROTECTED) + { + /*Default access mode (without authentication)*/ + /*--------------------------------------------*/ + if(guestAccessMode == DOCH_PART_ACCESS_MODE_NONE) + ioreq->irFlags |= (READ_PROTECTED | WRITE_PROTECTED); + else if(guestAccessMode == DOCH_PART_ACCESS_MODE_RO) + ioreq->irFlags |= WRITE_PROTECTED; + } + + /*Lock signal enabled/disabled*/ + /*----------------------------*/ + if(lockControl == DOCH_LOCK_ACTIVE) + ioreq->irFlags |= LOCK_ENABLED; + + /*Lock signal asserted*/ + /*--------------------*/ + if(hwLockSignal) + ioreq->irFlags |= LOCK_ASSERTED; + + /*Key inserted*/ + /*------------*/ + if(authenticated && protectionType != DOCH_PARTITION_NOT_PROTECTED) + ioreq->irFlags |= KEY_INSERTED; + + + /* SLOCK signal */ + /*--------------------------*/ + if(sLockSignal) + ioreq->irFlags |= STICKY_LOCK_ASSERTED; + + if( ((ioreq->irFlags & (WRITE_PROTECTED | READ_PROTECTED)) == 0) && + (protectionType != DOCH_PARTITION_NOT_PROTECTED) && (otpBit==0) ) + { + ioreq->irFlags |= KEY_INSERTED; + } + + /*OTW (Indicated by OTP Bit)*/ + /*--------------------------*/ + if(otpBit == 1) + { +#ifdef FL_SOTP + if (!sotp) + { +#endif /*FL_SOTP*/ + /* WRITE_PROTECTED and CHANGEABLE_PROTECTION added for compatibility with non-mDOC H3 devices */ + ioreq->irFlags |= (OTW_PROTECTED|WRITE_PROTECTED|CHANGEABLE_PROTECTION); +#ifdef FL_SOTP + } + else + { + ioreq->irFlags |= (OTW_PROTECTED); + } +#endif /*FL_SOTP*/ + } +#ifdef FL_SOTP + /* SOTP partition*/ + if (sotp) + { + ioreq->irFlags |= IDENTIFIED_SEQUENTIAL_OTP; + } +#endif /*FL_SOTP*/ + + /* check that no protection applied at all */ + if( (protectionType == DOCH_PARTITION_NOT_PROTECTED) && (ioreq->irFlags==0)) + return flNotProtected; + + return flOK; +}/*TFFSIdentifyProtection()*/ + + +/*----------------------------------------------------------------------*/ +/* f l R e m o v e P r o t e c t i o n K e y */ +/* b d k R e m o v e P r o t e c t i o n K e y */ +/* */ +/* Remove the protection key making the partition protected again */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSRemoveProtectionKey(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq myIoreq; + FLByte bPartNum; + DOCH_PartitionInfo * pDOCH_PartitionInfo = (DOCH_PartitionInfo*)dochVol.intermediateBuf; + + rc = flDOCHPartitionInfo(tffsAPISetIoreq(&myIoreq, ioreq->irHandle, 0,0, dochVol.intermediateBuf,0,0)); + if(rc != DOCH_OK) + { + /*If already protected - return DOCH_OK*/ + if(rc == DOCH_ProtectionFault) + return flOK; + + DBG_PRINT_ERR(FLZONE_API, "TFFSRemoveProtectionKey(): flDOCHPartitionInfo Failed with status : "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return TFFS_API_RET(rc); + } + if( (pDOCH_PartitionInfo->partitionAttributes2&DOCH_PA2B_PROTECTION_TYPE) == DOCH_PARTITION_NOT_PROTECTED) + { + if( (pDOCH_PartitionInfo->partitionAttributes2&DOCH_PA2B_LOCK_CTRL)!=0 ) + { + if( ((pDOCH_PartitionInfo->partitionAttributes2&DOCH_PA2B_GUEST_MODE)==DOCH_PART_ACCESS_MODE_FULL ) && + ((pDOCH_PartitionInfo->partitionAttributes2&DOCH_PA2B_USER_MODE) ==DOCH_PART_ACCESS_MODE_FULL ) ) + {/* both user and guest have full protection -> write protection not applied */ + return flOK; /* return OK for backward compatibility */ + } + } + else + { + return flNotProtected; /* trying to remove key from not-protected partition */ + } + }/* not protected partition */ + + + tffsset(&myIoreq,0,sizeof(myIoreq)); + myIoreq.irHandle = FL_GET_SOCKET_FROM_HANDLE(ioreq); + bPartNum = FL_GET_FLASH_PARTITION_FROM_HANDLE(ioreq); + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&myIoreq, bPartNum); + myIoreq.irFlags = DOCH_ACCESS_USER_PASSWORD; + /*Disable partition authentication*/ + /*--------------------------------*/ + rc = flDOCHDisablePartAccess(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSRemoveProtectionKey(): flDOCHDisablePartAccess Failed with status : "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + + return TFFS_API_RET(rc); + } + return flOK; +}/*TFFSRemoveProtectionKey()*/ + +/*----------------------------------------------------------------------*/ +/* f l C h a n g e P r o t e c t i o n K e y */ +/* b d k C h a n g e P r o t e c t i o n K e y */ +/* */ +/* Changes the current protection key with a new one. */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irData : Pointer to the new 8 bytes key array */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSChangeProtectionKey(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq myIoreq; + DOCH_PartitionUserAttrWithBinary* pPartitionUserAttrWithBinary = (DOCH_PartitionUserAttrWithBinary*)dochVol.intermediateBuf; + DOCH_PartitionProtectionAPI * pPartitionProtectionAPI = (DOCH_PartitionProtectionAPI *)dochVol.intermediateBuf; + + /*Retrieve partition info*/ + /*-----------------------*/ + rc = flDOCHGetParitionUserAttributes(tffsAPISetIoreq(&myIoreq, ioreq->irHandle,0,0,dochVol.intermediateBuf,0,0)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSChangeProtectionKey(): flDOCHGetParitionUserAttributes failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + if( pPartitionUserAttrWithBinary->bChangableProtection == FALSE ) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSChangeProtectionKey(): Can't change protection of unchangeable protection partition.\n"); + return flUnchangeableProtection; + } + + /*-----------------------*/ + /*Change passkey to new one*/ + /*-------------------------*/ + tffsset(dochVol.intermediateBuf, 0, sizeof(DOCH_PartitionProtectionAPI)); + tffscpy(pPartitionProtectionAPI->bPasskey, ioreq->irData, PROTECTION_KEY_LENGTH); + + /*Set new partition info (with new passkey) back to DOCH*/ + /*------------------------------------------------------*/ + rc = flDOCHSetParitionProtection(tffsAPISetIoreq(&myIoreq, ioreq->irHandle,DOCH_PASSKEY_VALID,0,dochVol.intermediateBuf,0,0)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSChangeProtectionKey(): flDOCHSetParitionProtection Failed with status : "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : TFFS_API_RET(rc) ; + } + return flOK; +}/*TFFSChangeProtectionKey()*/ + + +/*----------------------------------------------------------------------*/ +/* f l C h a n g e P r o t e c t i o n T y p e */ +/* b d k C h a n g e P r o t e c t i o n T y p e */ +/* */ +/* Changes the protection attributes of the partitions. */ +/* In order for a partition to change its protection type (without */ +/* reformatting the media) it must have the CHANGEABLE_PRTOECTION */ +/* attribute. */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irFlags : CHANGEABLE_PROTECTION - changeable protection type */ +/* PROTECTABLE - partition can receive protection */ +/* READ_PROTECTED - partition is read protected */ +/* WRITE_PROTECTED - partition is write protected */ +/* LOCK_ENABLED - HW lock signal is enabled */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSChangeProtectionType(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq myIoreq; + IOreq ioreq3; + FLBoolean read_protect, write_protect, locked; + FLDword guestAccessMode; + FLDword partitionAttr; + FLByte otwAsserted = ((ioreq->irFlags & OTW_PROTECTED) == OTW_PROTECTED); + DOCH_PartitionUserAttrWithBinary* pPartitionUserAttrWithBinary = (DOCH_PartitionUserAttrWithBinary*)dochVol.intermediateBuf; + DOCH_PartitionProtectionAPI * pPartitionProtectionAPI = (DOCH_PartitionProtectionAPI *)dochVol.intermediateBuf; + + /*Retrieve partition info*/ + /*-----------------------*/ + rc = flDOCHGetParitionUserAttributes(tffsAPISetIoreq(&myIoreq,ioreq->irHandle, 0,0,dochVol.intermediateBuf,0,0) ); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSChangeProtectionType(): flDOCHgetParitionUserAttributes failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + if (pPartitionUserAttrWithBinary->bChangableProtection == FALSE) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSChangeProtectionType(): Can't change protection of unchangeable protection partition.\n"); + return flUnchangeableProtection; + } + + /*If OTW_PROTECTED was asserted - lock the partition from further writing*/ + /*-----------------------------------------------------------------------*/ + if(otwAsserted) + { + if(ioreq->irFlags == (OTW_PROTECTED | PROTECTABLE | WRITE_PROTECTED)) + { + + /*Retrieve partition user attributes*/ + /*----------------------------------*/ + rc = flDOCHGetParitionUserAttributes(tffsAPISetIoreq(&myIoreq, ioreq->irHandle, 0,0,dochVol.intermediateBuf,0,0)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSChangeProtectionType(): flDOCHGetParitionUserAttributes failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + + /* change partition protection to non-changable */ + pPartitionUserAttrWithBinary->bChangableProtection = 0; + + /*Set attributes back to device*/ + /*----------------------------------*/ + rc = flDOCHSetParitionUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSChangeProtectionType(): flDOCHSetParitionUserAttributes Failed with status : "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + + /*Lock the partition as OTP */ + /*--------------------------*/ + tffsset(dochVol.intermediateBuf, 0, sizeof(DOCH_PartitionProtectionAPI)); + tffsAPISetIoreq(&myIoreq, ioreq->irHandle,DOCH_LOCK_AS_OTP,0,dochVol.intermediateBuf,0,0); + rc = flDOCHSetParitionProtection(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSChangeProtectionType(): DOCHSetParitionProtection failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + TFFS_API_RET_PART_FLSTATUS(rc, flWriteFault); + } + + return flOK; + } + else + { + return flBadParameter; + } + }/*OTW protection*/ + + /*Retrieve current partition info from DOCH*/ + /*-----------------------------------------*/ + rc = flDOCHPartitionInfo(tffsAPISetIoreq(&myIoreq, ioreq->irHandle, 0,0,dochVol.intermediateBuf,0,0)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSChangeProtectionType(): flDOCHPartitionInfo Failed with status : "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + partitionAttr = ((DOCH_PartitionInfo*)dochVol.intermediateBuf)->partitionAttributes2; + + /*Retrieve partition user attributes*/ + /*----------------------------------*/ + rc = flDOCHGetParitionUserAttributes(tffsAPISetIoreq(&myIoreq, ioreq->irHandle, 0,0,dochVol.intermediateBuf,0,0)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSChangeProtectionType(): flDOCHGetParitionUserAttributes failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + /*Change protection type + (only relevant fields are changed from the retrieved values!) + =============================================================*/ + pPartitionUserAttrWithBinary->bChangableProtection = + (((ioreq->irFlags & CHANGEABLE_PROTECTION) == CHANGEABLE_PROTECTION) + && (pPartitionUserAttrWithBinary->bChangableProtection == 1)); + + pPartitionUserAttrWithBinary->bProtected = ((ioreq->irFlags & PROTECTABLE) == PROTECTABLE); + + /*Set attributes back to device*/ + rc = flDOCHSetParitionUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSChangeProtectionType(): flDOCHSetParitionUserAttributes Failed with status : "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + + tffsset(dochVol.intermediateBuf, 0, (DOCH_SECTOR_SIZE)); + + /*Default access mode*/ + /*-------------------*/ + read_protect = ((ioreq->irFlags & READ_PROTECTED) == READ_PROTECTED); + write_protect = ((ioreq->irFlags & WRITE_PROTECTED) == WRITE_PROTECTED); + locked = ((ioreq->irFlags & LOCK_ENABLED) == LOCK_ENABLED); + if(read_protect) + guestAccessMode = DOCH_PART_ACCESS_MODE_NONE; + else if(write_protect) + guestAccessMode = DOCH_PART_ACCESS_MODE_RO; + else + guestAccessMode = DOCH_PART_ACCESS_MODE_FULL; + + DOCH_SetBits(&partitionAttr, DOCH_PA2B_GUEST_MODE, DOCH_PA2O_GUEST_MODE, guestAccessMode); + + if(guestAccessMode != DOCH_PART_ACCESS_MODE_FULL) + DOCH_SetBits(&partitionAttr, DOCH_PA2B_PROTECTION_TYPE, DOCH_PA2O_PROTECTION_TYPE, 1); + + /*Fill partPropApi structure*/ + /*--------------------------*/ + pPartitionProtectionAPI->dwProtectionType = + ((partitionAttr & DOCH_PA2B_PROTECTION_TYPE) >> DOCH_PA2O_PROTECTION_TYPE); + pPartitionProtectionAPI->dwUserAccessMode = + ((partitionAttr & DOCH_PA2B_USER_MODE) >> DOCH_PA2O_USER_MODE); + pPartitionProtectionAPI->dwGuestAccessMode = + ((partitionAttr & DOCH_PA2B_GUEST_MODE) >> DOCH_PA2O_GUEST_MODE); + pPartitionProtectionAPI->dwMasterControl = + ((partitionAttr & DOCH_PA2B_MASTER_CTRL) >> DOCH_PA2O_MASTER_CTRL); + pPartitionProtectionAPI->dwEncryptionType = + ((partitionAttr & DOCH_PA2B_ENCRYPT_TYPE) >> DOCH_PA2O_ENCRYPT_TYPE); + pPartitionProtectionAPI->dwLockControl = + ((partitionAttr & DOCH_PA2B_LOCK_CTRL) >> DOCH_PA2O_LOCK_CTRL); + pPartitionProtectionAPI->dwMaxNumOfAuthAttempts = + ((partitionAttr & DOCH_PA2B_MAX_AUTH_ATTEMPTS) >> DOCH_PA2O_MAX_AUTH_ATTEMPTS); + + if(locked == TRUE) + pPartitionProtectionAPI->dwLockControl = DOCH_LOCK_ACTIVE; + else + pPartitionProtectionAPI->dwLockControl = DOCH_LOCK_NOT_ACTIVE; + + /*Set new partition info (with new protection type) back to DOCH*/ + /*--------------------------------------------------------------*/ + rc = flDOCHSetParitionProtection(tffsAPISetIoreq(&myIoreq,ioreq->irHandle,DOCH_ATTRIBUTES_VALID,0,dochVol.intermediateBuf,0,0)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSChangeProtectionType(): flDOCHSetParitionProtection Failed with status : "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return rc==DOCH_ProtectionFault ? flHWProtection : TFFS_API_RET(rc); + } + + /*If all is well, disable access to the partition*/ + /* (Is reset needed???? - TBD)*/ + return TFFSRemoveProtectionKey(tffsAPISetIoreq(&ioreq3,ioreq->irHandle,0,0,0,0,0)); +}/*TFFSChangeProtectionType()*/ + +/*----------------------------------------------------------------------*/ +/* f l A p p l y S t i c k y L o c k */ +/* */ +/* Enable the sticky lock mode to all relevant partitions */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Must be set to 0 */ +/* bits 3-0 - Socket # (zero based) */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSApplyStickyLock(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq myIoreq; + + rc = DOCHConfigHW(tffsAPISetIoreq(&myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq), DOCH_SLOCK, 0,0,DOCH_SLOCK_ACTIVE,0)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSApplyStickyLock(): DOCHConfigHW Failed with status : "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return flBadFunction; + } + + return flOK; +}/*TFFSApplyStickyLock*/ + + +/*-----------------------------------------*/ +/* Function name : TFFSHwProtectionLock*/ +/* Description : */ +/* Return type : static FLStatus */ +/* Argument : IOreq* ioreq*/ +/*-----------------------------------------*/ +static FLStatus TFFSHwProtectionLock(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq myIoreq; + FLDword partitionAttr; + DOCH_PartitionProtectionAPI * pPartitionProtectionAPI = (DOCH_PartitionProtectionAPI*)dochVol.intermediateBuf; + + /*Retrieve current partition info from DOCH*/ + /*-----------------------------------------*/ + rc = flDOCHPartitionInfo(tffsAPISetIoreq(&myIoreq, ioreq->irHandle,0,0,dochVol.intermediateBuf,0,0)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSHwProtectionLock(): flDOCHPartitionInfo Failed with status : "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + partitionAttr = ((DOCH_PartitionInfo*)dochVol.intermediateBuf)->partitionAttributes2; + + tffsset(dochVol.intermediateBuf, 0, sizeof(DOCH_PartitionProtectionAPI)); + + /*Lock signal*/ + /*-----------*/ + if((ioreq->irFlags & LOCK_ENABLED) == LOCK_ENABLED) + DOCH_SetBits(&partitionAttr, DOCH_PA2B_LOCK_CTRL, DOCH_PA2O_LOCK_CTRL, DOCH_LOCK_ACTIVE); + else + DOCH_SetBits(&partitionAttr, DOCH_PA2B_LOCK_CTRL, DOCH_PA2O_LOCK_CTRL, DOCH_LOCK_NOT_ACTIVE); + + /*Fill partPropApi structure*/ + /*--------------------------*/ + pPartitionProtectionAPI->dwProtectionType = + ((partitionAttr & DOCH_PA2B_PROTECTION_TYPE) >> DOCH_PA2O_PROTECTION_TYPE); + pPartitionProtectionAPI->dwUserAccessMode = + ((partitionAttr & DOCH_PA2B_USER_MODE) >> DOCH_PA2O_USER_MODE); + pPartitionProtectionAPI->dwGuestAccessMode = + ((partitionAttr & DOCH_PA2B_GUEST_MODE) >> DOCH_PA2O_GUEST_MODE); + pPartitionProtectionAPI->dwMasterControl = + ((partitionAttr & DOCH_PA2B_MASTER_CTRL) >> DOCH_PA2O_MASTER_CTRL); + pPartitionProtectionAPI->dwEncryptionType = + ((partitionAttr & DOCH_PA2B_ENCRYPT_TYPE) >> DOCH_PA2O_ENCRYPT_TYPE); + pPartitionProtectionAPI->dwLockControl = + ((partitionAttr & DOCH_PA2B_LOCK_CTRL) >> DOCH_PA2O_LOCK_CTRL); + pPartitionProtectionAPI->dwMaxNumOfAuthAttempts = + ((partitionAttr & DOCH_PA2B_MAX_AUTH_ATTEMPTS) >> DOCH_PA2O_MAX_AUTH_ATTEMPTS); + + /*Set modified partition info*/ + /*---------------------------*/ + rc = flDOCHSetParitionProtection(tffsAPISetIoreq(&myIoreq, ioreq->irHandle,DOCH_ATTRIBUTES_VALID,0,dochVol.intermediateBuf,0,0)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSHwProtectionLock(): flDOCHSetParitionProtection Failed with status : "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : TFFS_API_RET(rc) ; + } + return flOK; +}/*TFFSHwProtectionLock()*/ +#ifdef FL_SLPP +/*----------------------------------------------------------------------*/ +/* f l S L P P U n l o c k R a n g e */ +/* */ +/* Unlock a range of sectors on a sector protected partition. */ +/* */ +/* Parameters: */ +/* irHandle : Bits 3-0 - Socket # (zero based) */ +/* irCount : First sector to unlock */ +/* irLength : Number of sectors to unlock */ +/* irData : Pointer to an 8 bytes passkey array */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSSLPPUnlockRange(IOreq* ioreq) +{ + DOCH_Error rc; + + rc = flDOCHSLPPUnlockRange(ioreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSSLPPUnlockRange(): flDOCHSLPPUnlockRange failed with status: 0x%x \r\n\r\n"), rc)); + + if(rc == DOCH_ProtectionFault) + return flHWProtection; + else + return flGeneralFailure; + } + return flOK; +}/*TFFSSLPPUnlockRange*/ + +/*----------------------------------------------------------------------*/ +/* f l S L P P L o c k R a n g e */ +/* */ +/* Lock a range of sectors on a sector protected partition. */ +/* */ +/* Parameters: */ +/* irHandle : Bits 3-0 - Socket # (zero based) */ +/* irCount : First sector to lock */ +/* irLength : Number of sectors to lock */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSSLPPLockRange(IOreq* ioreq) +{ + DOCH_Error rc; + + rc = flDOCHSLPPLockRange(ioreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSSLPPLockRange(): flDOCHSLPPLockRange failed with status: 0x%x \r\n\r\n"), rc)); + + if(rc == DOCH_ProtectionFault) + return flHWProtection; + else + return flGeneralFailure; + } + return flOK; +}/*TFFSSLPPLockRange*/ + +/*----------------------------------------------------------------------*/ +/* f l S L P P U n l o c k E n t i r e P a r t i t i o n */ +/* */ +/* Unlock all sectors on a sector protected partition. */ +/* */ +/* Parameters: */ +/* irHandle : Bits 3-0 - Socket # (zero based) */ +/* irData : Pointer to an 8 bytes passkey array */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSSLPPUnlockEntirePartition(IOreq* ioreq) +{ + DOCH_Error rc; + + rc = flDOCHSLPPUnlockEntirePartition(ioreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSSLPPUnlockEntirePartition(): flDOCHSLPPUnlockEntirePartition failed with status: 0x%x \r\n\r\n"), rc)); + + if(rc == DOCH_ProtectionFault) + return flHWProtection; + else + return flGeneralFailure; + } + return flOK; +}/*TFFSSLPPUnlockEntirePartition*/ + +/*----------------------------------------------------------------------*/ +/* f l S L P P S t i c k y L o c k R a n g e */ +/* */ +/* Sticky lock a range of sectors on a sector protected partition. */ +/* */ +/* Parameters: */ +/* irHandle : Bits 3-0 - Socket # (zero based) */ +/* irCount : First sector to sticky lock */ +/* irLength : Number of sectors to sticky lock */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSSLPPStickLockRange(IOreq* ioreq) +{ + DOCH_Error rc; + + rc = flDOCHSLPPStickyLockRange(ioreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSSLPPStickLockRange(): flDOCHSLPPStickyLockRange failed with status: 0x%x \r\n\r\n"), rc)); + + if(rc == DOCH_ProtectionFault) + return flHWProtection; + else + return flGeneralFailure; + } + return flOK; +}/*TFFSSLPPStickLockRange*/ + +/*----------------------------------------------------------------------*/ +/* f l S L P P R e p o r t L o c k e d R a n g e s */ +/* */ +/* Report currently defined unlocked/stick locked ranges on a sector */ +/* protected partition. */ +/* */ +/* Parameters: */ +/* irHandle : Bits 3-0 - Socket # (zero based) */ +/* irData : Pointer to DOCH_SLPPReport structure */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/* irCount : Number of currently defined ranges */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSSLPPReportLockedRanges(IOreq* ioreq) +{ + DOCH_Error rc; + + DOCH_SLPPReport* slppRep = (DOCH_SLPPReport*)ioreq->irData; + + rc = flDOCHSLPPReportRanges(ioreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSSLPPReportLockedRanges(): flDOCHSLPPStickyLockRange failed with status: 0x%x \r\n\r\n"), rc)); + + if(rc == DOCH_ProtectionFault) + return flHWProtection; + else + return flGeneralFailure; + } + + ioreq->irCount = slppRep->numOfActiveRanges; + + return flOK; +}/*TFFSSLPPReportLockedRanges*/ +#endif /*FL_SLPP*/ + +/*----------------------------------------------------------------------*/ +/* Function name : TFFSPassThrough*/ +/* Description : calls to DOCH pass through command with converted */ +/* parameters */ +/* Return type : FLStatus */ +/* Argument : IOreq FAR2 *ioreq*/ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* irData : pointer to user buffer (for DATA IN and DATA out */ +/* commands) */ +/* irLength : number of sectors in buffer, pointed to by irData*/ +/* irCount : bits 0..1 - pass through operation flow, where */ +/* 0 - No Data(CTRL), 1 - Data IN, 2 - Data OUT */ +/* bit 2 - 1, when interrupt should be used, */ +/* 0 - otherwise */ +/* bits 4..7 - frame size exponent, should be set */ +/* to 0 for now - 1 sector */ +/* irPath : pointer to buffer from type DOCH_Registers* */ +/* IN - input registers, OUT - out registers */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +FLStatus TFFSPassThrough(IOreq FAR2 *ioreq) +{ + DOCH_Error rc; + /*IOreq myIoreq;*/ + FLSNative snFlow = (FLSNative)(ioreq->irCount & 0x00000003); + FLBoolean fUseInterrupt = (FLBoolean)((ioreq->irCount&0x00000004)>>2); + /*FLDword dwMultSectorFrame = (FLDword)(ioreq->irCount&0x00000f0)>>4);*/ + /*DOCH_Socket* pDev = DOCH_get_socket(FL_GET_SOCKET_FROM_HANDLE(ioreq));*/ + + /* TODO - add retrieve current transfer mode from device */ + + rc = DOCHAtaPassThrough( FL_GET_SOCKET_FROM_HANDLE(ioreq), snFlow, + (DOCH_Registers*)ioreq->irPath, (DOCH_Registers*)ioreq->irPath, + (FLNative)ioreq->irLength, (void*)ioreq->irData, fUseInterrupt); + + return (rc==DOCH_ATA_NO_ERROR)?flOK : flGeneralFailure; +}/*TFFSPassThrough()*/ + + +/*----------------------------------------------------------------------*/ +/* b d C a l l B C T o S D K */ +/* */ +/* Performs needed general operations before calling actual function */ +/* Calls appropriate TFFS function (that will convert to SDK routine(s))*/ +/* */ +/* Parameters: */ +/* functionNo : DOCH SDK function to run */ +/* ioreq : DOCH ioreq structure */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +FLStatus bdCallTFFSToDOCH(FLFunctionNo functionNo, IOreq FAR2 *ioreq) +{ + FLStatus rc = flFeatureNotSupported; + DOCH_Error dochRc; + IOreq myIoreq; + FLByte partNum; + FLByte partNumTemp = 0; + FLHandle origIrHandle; + DOCH_DiskUserAttrWithBinary* pDiskUserAttrWithBinary; + IOreq ioreq1; + + /*Sanity Check*/ + /*------------*/ + if(ioreq == NULL) + { + DBG_PRINT_ERR(FLZONE_BLKDEV,"bdCallTFFSToDOCH: - Ioreq is NULL"); + return flBadParameter; + } + + origIrHandle = ioreq->irHandle; + + /* Actions to take on the first time bdCallTFFSToDOCH is invoked */ + /*---------------------------------------------------------------*/ + if(dochBdCallWasCalled == FALSE) + { + checkStatus(flInit()); + tffsset (&dochVol, 0, sizeof(dochVol)); + checkStatus(flCreateMutex(&dochVol.mutex)); + + dochVol.intermediateBuf = (FLByte*)FL_MALLOC(DOCH_SECTOR_SIZE); + if (dochVol.intermediateBuf == NULL) + { + DBG_PRINT_ERR(FLZONE_API, "bdCallTFFSToDOCH(): Can't allocate intermediate buffer.\r\n"); + return flNotEnoughMemory; + } + + dochBdCallWasCalled = TRUE; + }/* dochBdCallWasCalled was called */ + + /* Actions to take on first bdCallTFFSToDOCH that is Not RECOVER_FROM_POWER_LOSS */ + /*-------------------------------------------------------------------------------*/ + if (dochGotDiskUserAttributes == FALSE && functionNo != FL_RECOVER_FROM_POWER_LOSS) + { + /*Retrieve diskAttributes at least once*/ + /*(numOfBinaryPartitions, iplExists, otpExists will be further updated + by TFFSflashFormat if called) + ---------------------------*/ + dochRc = flDOCHGetDiskUserAttributes(tffsAPISetIoreq(&myIoreq, 0,0,0,dochVol.intermediateBuf,0,0)); + if(dochRc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "bdCallTFFSToDOCH(): flDOCHGetDiskUserAttributes failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), dochRc)); +#ifdef CHECK_POWER_ON_EVERY_COMMAND + if( gDeviceTurnedOff==DOCH_GLOBAL_BOOL_PATTERN ) + return flSuspendModeDetected; +#endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + return flGeneralFailure; + } + + pDiskUserAttrWithBinary =(DOCH_DiskUserAttrWithBinary*)dochVol.intermediateBuf; + + dochVol.numOfBinaryPartitions = pDiskUserAttrWithBinary->bNumOfBinaryPartitions; + dochVol.iplExists = pDiskUserAttrWithBinary->bIplPresent; + dochVol.otpExists = pDiskUserAttrWithBinary->bOtpPresent; + + dochGotDiskUserAttributes = TRUE; + }/* dochGotDiskUserAttributes */ + + /* get partition number and check it up to call type */ + partNum = FL_GET_FLASH_PARTITION_FROM_HANDLE(ioreq); + if((functionNo >= INDEX_BINARY_START) && (functionNo <= INDEX_BINARY_END)) + {/* binary partition */ + + /* check that the number of binary partition not exceeded number of BDK on the device */ + if( partNum >= dochVol.numOfBinaryPartitions ) + return flBadDriveHandle; + + rc = actualPartitionNum(&partNum, PARTITION_TYPE_BINARY, FL_GET_SOCKET_FROM_HANDLE(ioreq)); + if(rc != flOK) + { + DBG_PRINT_ERR(FLZONE_API, "bdCallTFFSToDOCH(): actualPartitionNum failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return rc; + } + ioreq->irHandle &= (0xFFFFFF0F); + ioreq->irHandle |= (partNum << 4); + } + else + { + if((functionNo >= INDEX_NEED_PARTITION_0_START) && (functionNo <= INDEX_NEED_PARTITION_0_END)) + {/* calls, which required partition number zero */ + if( partNum!=0 ) + return flBadDriveHandle; + } + else + { + if(functionNo > INDEX_NEED_PARTITION_0_END) + {/* BDTL partition */ + rc = actualPartitionNum(&partNum, PARTITION_TYPE_BDTL, FL_GET_SOCKET_FROM_HANDLE(ioreq)); + if(rc != flOK) + { + DBG_PRINT_ERR(FLZONE_API, "bdCallTFFSToDOCH(): actualPartitionNum failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return rc; + } + ioreq->irHandle &= (0xFFFFFF0F); + ioreq->irHandle |= (partNum << 4); + } + /* otherwise -> Files calls - different treatment */ + } + } + + /*make sure specific function precondition*/ + if (!flTakeMutex(&dochVol.mutex)) + return flDriveNotAvailable; + switch(functionNo) + { + case FL_ABS_READ: + case FL_ABS_WRITE: + case FL_ABS_DELETE: + case FL_ABS_SECURE_DELETE: + case FL_SECTORS_IN_VOLUME: + if (dochVol.mountCount[partNum] == 0) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("bdCallTFFSToDOCH(): Media must be mounted before calling 0x%d function\r\n"), functionNo)); + flFreeMutex(&dochVol.mutex); + return flNotMounted; + } + break; + case BD_ERASE_BD: + if (dochVol.mountCount[partNum] != 0) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("bdCallTFFSToDOCH(): Media must be unmounted before calling 0x%d function\r\n"), functionNo)); + flFreeMutex(&dochVol.mutex); + return flNoWriteAccess; + } + break; + + case BD_FLASH_FORMAT: + case BD_UNFORMAT: + for (partNumTemp = 0; partNumTemp < DOCH_MAX_PARTITIONS; partNumTemp++) + { + if (dochVol.mountCount[partNumTemp] != 0) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("bdCallTFFSToDOCH(): All partitions must be unmounted before calling 0x%d function\n"), functionNo)); + flFreeMutex(&dochVol.mutex); + return flNoWriteAccess; + } + } + default: + break; + } + + /*Branch to appropriate TFFS routine according to function#*/ + /*---------------------------------------------------------*/ + + switch(functionNo) + { +#ifdef FL_EXTENDED_DISK_INFO + case FL_GET_EXTENDED_DISK_INFO: + rc = TFFSGetExtendedDiskInfo(ioreq); + break; + +#endif /* FL_EXTENDED_DISK_INFO */ + case FL_VOLUME_INFO: + rc = TFFSVolumeInfo(ioreq); + break; + + case FL_COUNT_VOLUMES: + rc = TFFSCountVolumes(ioreq); + break; + + case FL_SECTORS_IN_VOLUME: + rc = TFFSSectorsInVolume(ioreq); + break; + +/* Quick mount routines */ +#ifndef FL_NO_QUICK_MOUNT_FEATURE + case FL_CLEAR_QUICK_MOUNT_INFO: + rc = TFFSClearQuickMountInfo(ioreq); + break; + + case FL_WRITE_QUICK_MOUNT_INFO: + rc = TFFSWriteQuickMountInfo(ioreq); + break; + + case FL_GET_QUICK_MOUNT_STATUS: + rc = TFFSGetQuickMountStatus(ioreq); + break; + +#endif /* FL_NO_QUICK_MOUNT_FEATURE */ + +/* Volume mounting routines */ + case FL_ABS_MOUNT: + rc = TFFSAbsMountVolume(ioreq); + break; + + case FL_DISMOUNT_VOLUME: + rc = TFFSAbsDismountVolume(ioreq); + break; + + case FL_CHECK_VOLUME: + rc = TFFSCheckVolume(ioreq); + break; + +/* Media */ +#ifndef FL_READ_ONLY + case FL_DEFRAGMENT_VOLUME: + rc = TFFSDefragmentVolume(ioreq); + break; + + +#ifdef FL_FORMAT_VOLUME + case BD_FLASH_FORMAT: + rc = TFFSflashFormat(ioreq); + break; + + case BD_UNFORMAT: + rc = TFFSUnFormat(ioreq); + break; + + case BD_ERASE_BD: + rc = TFFSEraseBD(ioreq); + break; + + +#endif /* FL_FORMAT_VOLUME */ +#endif /* FL_READ_ONLY */ + +/* IO */ +#ifdef FL_ABS_READ_WRITE + case FL_ABS_READ: + ioreq->irFlags = 0; + rc = TFFSAbsRead(ioreq, &(ioreq->irSectorCount)); + break; + + case FL_ABS_ADDRESS: + rc = TFFSAbsAddress(ioreq); + break; + + +#ifndef FL_READ_ONLY + case FL_ABS_WRITE: + ioreq->irFlags = 0; + rc = TFFSAbsWrite(ioreq); + break; + + case FL_ABS_DELETE: + rc = TFFSAbsDelete(ioreq); + break; + + case FL_ABS_SECURE_DELETE: + rc = TFFSAbsSecureDelete(ioreq); + break; + +#endif /* FL_READ_ONLY */ +#endif /* FL_ABS_READ_WRITE */ + + case FL_GET_PHYSICAL_INFO: + rc = TFFSGetPhysicalInfo(ioreq); + break; + +/* BDK routines (obsolete) */ +#ifdef BDK_ACCESS + case FL_BINARY_READ_INIT: + rc = TFFSbdkReadInit(ioreq); + break; + + case FL_BINARY_READ_BLOCK: + rc = TFFSbdkReadBlock(ioreq); + break; + +#ifndef FL_READ_ONLY + case FL_BINARY_WRITE_INIT: + rc = TFFSbdkWriteInit(ioreq); + break; + + case FL_BINARY_WRITE_BLOCK: + rc = TFFSbdkWriteBlock(ioreq); + break; + + case FL_BINARY_ERASE: + rc = TFFSbdkErase(ioreq); + break; + + case FL_BINARY_CREATE: + rc = TFFSbdkCreate(ioreq); + break; +#endif /* FL_READ_ONLY */ + + case FL_BINARY_PARTITION_INFO: + rc = TFFSbdkPartitionInfo(ioreq); + break; +#endif /* BDK_ACCESS */ + +/* OTP routines */ +#ifdef HW_OTP + case FL_OTP_SIZE: + rc = TFFSOTPSize(ioreq); + break; + + case FL_OTP_READ: + rc = TFFSOTPRead(ioreq); + break; + + case FL_OTP_WRITE: + rc = TFFSOTPWriteAndLock(ioreq); + break; + + case FL_UNIQUE_ID: + rc = TFFSGetUniqueID(ioreq); + break; + + case FL_CUSTOMER_ID: + rc = TFFSGetCustomerID(ioreq); + break; + +#endif /* HW_OTP */ + + case FL_RECOVER_FROM_POWER_LOSS: + rc = TFFSRecoverFromPowerLoss(ioreq); + break; + + case FL_DEEP_POWER_DOWN_MODE: + rc = TFFSDeepPowerDownMode(ioreq); + break; + + case FL_HW_CONFIG: + rc = TFFSHwConfig(ioreq); + break; + + +/* IPL routines */ +#ifndef NO_IPL_CODE + case FL_WRITE_IPL: + rc = TFFSWriteIPL(ioreq); + break; + + case FL_READ_IPL: + rc = TFFSReadIPL(ioreq); + break; +#endif /*NO_IPL_CODE*/ + + +/* Protection routines */ + case FL_PROTECTION_GET_TYPE: + case FL_BINARY_PROTECTION_GET_TYPE: + case FL_IPL_PROTECTION_GET_TYPE: + rc = TFFSIdentifyProtection(ioreq); + break; + + case FL_IPL_PROTECTION_INSERT_KEY:/* dont break after inserting default key */ + /* don't insert default key in order not to reduce number of authentication tries*/ + /*TFFSInsertProtectionKey(tffsAPISetIoreq(&ioreq1, 0, 0,0,(void*)DEFAULT_KEY,0,0));*/ + case FL_PROTECTION_INSERT_KEY: + case FL_BINARY_PROTECTION_INSERT_KEY: + rc = TFFSInsertProtectionKey(ioreq); + break; + + case FL_PROTECTION_REMOVE_KEY: + case FL_BINARY_PROTECTION_REMOVE_KEY: + case FL_IPL_PROTECTION_REMOVE_KEY: + rc = TFFSRemoveProtectionKey(ioreq); + break; + + case FL_IPL_PROTECTION_CHANGE_KEY: /* dont break after inserting default key */ + TFFSInsertProtectionKey(tffsAPISetIoreq(&ioreq1, 0, 0,0,(void*)DEFAULT_KEY,0,0)); + case FL_PROTECTION_CHANGE_KEY: + case FL_BINARY_PROTECTION_CHANGE_KEY: + rc = TFFSChangeProtectionKey(ioreq); + break; + + case FL_IPL_PROTECTION_CHANGE_TYPE:/* dont break after inserting default key */ + TFFSInsertProtectionKey(tffsAPISetIoreq(&ioreq1, 0, 0,0,(void*)DEFAULT_KEY,0,0)); + case FL_PROTECTION_CHANGE_TYPE: + case FL_BINARY_PROTECTION_SET_TYPE: + rc = TFFSChangeProtectionType(ioreq); + break; + + case FL_PROTECTION_STICKY_LOCK: + rc = TFFSApplyStickyLock(ioreq); + break; + + case FL_PROTECTION_SET_LOCK: + case FL_BINARY_PROTECTION_CHANGE_LOCK: + rc = TFFSHwProtectionLock(ioreq); + break; +#ifdef FL_SLPP + case FL_SLPP_UNLOCK_RANGE: + rc = TFFSSLPPUnlockRange(ioreq); + break; + + case FL_SLPP_LOCK_RANGE: + rc = TFFSSLPPLockRange(ioreq); + break; + + case FL_SLPP_UNLOCK_ENTIRE_PARTITION: + rc = TFFSSLPPUnlockEntirePartition(ioreq); + break; + + case FL_SLPP_STICKY_LOCK_RANGE: + rc = TFFSSLPPStickLockRange(ioreq); + break; + + case FL_SLPP_REPORT_LOCKED_RANGES: + rc = TFFSSLPPReportLockedRanges(ioreq); + break; +#endif /*FL_SLPP*/ + + case FL_DOCH_PASS_THROUGH: + rc = TFFSPassThrough(ioreq); + break; + + default: + DBG_PRINT_ERR_PRM(FLZONE_BLKDEV,(FLTXT("bdCallTFFSToDOCH: - Undefined Function# %d.\r\n"),functionNo)); + rc = flFeatureNotSupported; + break; + } + + /*Reset irHandle to original value*/ + ioreq->irHandle = origIrHandle; + flFreeMutex(&dochVol.mutex); +#ifdef CHECK_POWER_ON_EVERY_COMMAND + if( gDeviceTurnedOff==DOCH_GLOBAL_BOOL_PATTERN ) + return flSuspendModeDetected; +#endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + return rc; +} + + +/*static +FLStatus TFFSCheckBeforeWrite(IOreq* ioreq) { return flFeatureNotSupported;}*/ + + +/*----------------------------------------------------------------------*/ +/* f l S e t D o c B u s R o u t i n e */ +/* */ +/* Set user defined memory access routines for DOCH. */ +/* */ +/* Parameters: */ +/* socket : Socket number to install routine for. */ +/* structPtr : Pointer to function structure. */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +TFFS_DLL_API FLStatus NAMING_CONVENTION DochSetDocBusRoutine(FLByte socket, + FLAccessStruct FAR1 * structPtr) +{ + return flOK; +} + +/*----------------------------------------------------------------------*/ +/* f l G e t D o c B u s R o u t i n e */ +/* */ +/* Get currently installed memory access routines for DOCH. */ +/* */ +/* Parameters: */ +/* socket : Socket number to install routine for. */ +/* structPtr : Pointer to function structure. */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +TFFS_DLL_API FLStatus NAMING_CONVENTION DochGetDocBusRoutine(FLByte socket, + FLAccessStruct FAR1 * structPtr) +{ + return flOK; +} + + +/*----------------------------------------------------------------------*/ +/* f l R e g i s t e r D O C H 3 S O C */ +/* */ +/* Register DOCH3 socket */ +/* */ +/* Parameters: */ +/* dwAddress : Address were DOCH socket is located */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failure */ +/* 'noOfSockets' is incremented in case a socket was found */ +/*----------------------------------------------------------------------*/ +FLStatus flRegisterDOCH3SOC(FLDword dwAddress) +{ + DOCH_Error rc; + +#ifndef DOCH_USE_FUNC + DOCHFlash->win = (volatile FLByte FAR0*)physicalToPointer(dwAddress, DOCH_MEM_WIN_SIZE, 0); +#endif /*DOCH_USE_FUNC*/ + + rc = DochRegisterSocket(dwAddress); + if(rc != DOCH_OK) + return flAdapterNotFound; + + noOfSockets++; + return flOK; +}/*flRegisterDOCH3SOC*/ + +/*----------------------------------------------------------------------*/ +/* t f f s A p i E x i t */ +/* */ +/* Exit routine for tffs_api.c layer */ +/* */ +/* Parameters: */ +/* NONE */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failure */ +/*----------------------------------------------------------------------*/ +FLStatus tffsApiExit(void) +{ + DBG_PRINT_FLOW(FLZONE_ABS, "tffsApiExit() Invoked \r\n\n"); + + if( dochVol.intermediateBuf!=NULL ) + { + FL_FREE(dochVol.intermediateBuf); + dochVol.intermediateBuf = NULL; + } + noOfSockets = 0; + DochSDKExit(); + flDeleteMutex(&dochVol.mutex); + return flOK; +} + + +/*----------------------------------------------------------------------*/ +/* Function name : tffsApiSetAutoDpd*/ +/* Description : sets */ +/* Return type : FLStatus */ +/* Argument : FLSDword dwsSocket*/ +/* Argument : FLDword value*/ +/* Argument : FLDword FAR2 *prevValue*/ +/*----------------------------------------------------------------------*/ +FLStatus tffsApiSetAutoDpd( FLEnvVars envVarType, FLSDword dwsSocket, FLDword value, FLDword FAR2 *prevValue ) +{ + IOreq myIoreq; + +#ifdef DOCH_AUTO_DPD_BY_HOST + + if( envVarType!=TFFS_API_IS_AUTO_DPD_ON(dwsSocket) ) + return flFeatureNotSupported; + + (*prevValue) = TFFS_API_IS_AUTO_DPD_ON(dwsSocket) ? TRUE : FALSE; + + tffsAPISetIoreq( &myIoreq, dwsSocket, DOCH_ENV_AUTO_DPD_BY_HOST, 0,0, value, 0); + if (flDOCHSetEnvVar(&myIoreq) != DOCH_OK) + return flFeatureNotSupported; + + TFFS_API_SAVE_POWER_MODES(dwsSocket) = 0xFFFFFFFF; + return flOK; + +#else /*DOCH_AUTO_DPD_BY_HOST*/ + FLDword dwMode; + FLBoolean bAutoDpdOn = TFFS_API_IS_AUTO_DPD_ON(dwsSocket) ? TRUE : FALSE; + DOCH_Error rc; + + switch( envVarType) /* set IOREQ values */ + { + case FL_SET_AUTO_DPD_MODE: + dwMode = gDpdSettings.activeMode; + if( value == FL_ON )/*DPD is ON, device may be in DPD, idle or Active state */ + { + /* fix active mode to enable auto DPD */ + if( dwMode == DOCH_WM_NORMAL ) + dwMode = DOCH_WM_NORMAL_AND_AUTO_STBY; + if( dwMode == DOCH_WM_LOW_FREQ ) + dwMode = DOCH_WM_LOW_FREQ_AND_AUTO_STBY; + + tffsAPISetIoreq( &myIoreq, dwsSocket, (DOCH_PM_SET_BOTH_MODES|DOCH_PM_INACTIVE_MODE), + 0,0, gDpdSettings.timeOut, (dwMode | gDpdSettings.inActiveMode)); + } + else /* set the device to 'always ON' mode */ + { + /* fix active mode to disable auto DPD */ + if( dwMode == DOCH_WM_NORMAL_AND_AUTO_STBY ) + dwMode = DOCH_WM_NORMAL; + if( dwMode == DOCH_WM_LOW_FREQ_AND_AUTO_STBY ) + dwMode = DOCH_WM_LOW_FREQ; + + tffsAPISetIoreq( &myIoreq, dwsSocket, (DOCH_PM_SET_BOTH_MODES|DOCH_PM_INACTIVE_MODE), + 0,0,gDpdSettings.timeOut, (dwMode | gDpdSettings.inActiveMode)); + } + + (*prevValue) = bAutoDpdOn; + TFFS_API_SAVE_POWER_MODES(dwsSocket); + break; + + case FL_SET_ACTIVE_DPD_MODE: + dwMode = value; /* copy value to init this variable */ + if(bAutoDpdOn == FL_ON ) + { + if( value == DOCH_WM_NORMAL ) + dwMode = DOCH_WM_NORMAL_AND_AUTO_STBY; + if( value == DOCH_WM_LOW_FREQ ) + dwMode = DOCH_WM_LOW_FREQ_AND_AUTO_STBY; + } + else + { + if( value == DOCH_WM_NORMAL_AND_AUTO_STBY ) + dwMode = DOCH_WM_NORMAL; + if( value == DOCH_WM_LOW_FREQ_AND_AUTO_STBY ) + dwMode = DOCH_WM_LOW_FREQ; + } + + (*prevValue) = gDpdSettings.activeMode; + tffsAPISetIoreq(&myIoreq, dwsSocket, (DOCH_PM_SET_BOTH_MODES | DOCH_PM_INACTIVE_MODE), + 0,0, gDpdSettings.timeOut, (dwMode|gDpdSettings.inActiveMode) ); + break; + + case FL_SET_INACTIVE_DPD_MODE: + (*prevValue) = gDpdSettings.inActiveMode; + /* must leave device in inactive mode */ + tffsAPISetIoreq(&myIoreq, dwsSocket, (DOCH_PM_SET_BOTH_MODES | DOCH_PM_INACTIVE_MODE), + 0,0, gDpdSettings.timeOut, (value|gDpdSettings.activeMode) ); + break; + + case FL_SET_TIMEOUT_DPD: + /* reset both modes + set timeout */ + (*prevValue) = gDpdSettings.timeOut; + tffsAPISetIoreq( &myIoreq, dwsSocket, (DOCH_PM_SET_BOTH_MODES|DOCH_PM_INACTIVE_MODE),0,0, + value, (gDpdSettings.activeMode|gDpdSettings.inActiveMode) ); + break; + + default: + return flFeatureNotSupported; + }/*switch*/ + + rc = DOCHSetPowerMode(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "tffsApiSetAutoDpd(): DOCHSetPowerMode failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return TFFS_API_RET(rc); + } + return flOK; +#endif /*DOCH_AUTO_DPD_BY_HOST*/ +}/*tffsApiSetAutoDpd()*/ + + +/************************************************************************/ +/* internal functions */ +/************************************************************************/ + +/************************************************************************/ +/* Function name : tffsApiAuthPartition*/ +/* Description : authenticates H3 partition */ +/* Return type : FLStatus - flOK, flWrongKey or flGeneralFailure*/ +/* Argument : IOreq * myIoreq*/ +/* Argument : IOreq * ioreq*/ +/* Argument : FLByte bPartNo - number of partition up to H3 count */ +/* Argument : FLByte * pKey - key */ +/* Argument : FLWord wKeyLen - length of the key pointed to by pKey*/ +/************************************************************************/ +static FLStatus tffsApiAuthPartition(IOreq * myIoreq, IOreq * ioreq, FLByte bPartNo, FLByte * pKey, FLWord wKeyLen) +{ + DOCH_Error rc; + DOCH_PartitionAcessPassword * pPartitionAcessPassword = (DOCH_PartitionAcessPassword *)(dochVol.intermediateBuf); + DOCH_PartitionInfo * partInfoPtr = (DOCH_PartitionInfo *)dochVol.intermediateBuf; + + + /* non mDOC H3 devices return flOK, when wrong key inserted to partition with CHNAGABLE + protection only. So first determine, which protection we have */ + tffsAPISetIoreq(myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq), 0, 0, dochVol.intermediateBuf, 0, 0); + DOCH_SET_PARTITION_TO_IOREQ_HANDLE( myIoreq, bPartNo ); + rc = flDOCHPartitionInfo(myIoreq); + if( rc != DOCH_OK ) + { + /*In case of Read and Write protection, we might not be able to retrieve the partition info*/ + if(rc == DOCH_ProtectionFault) + goto authenticateOnly; + + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } +#ifndef FL_OTP + if( (partInfoPtr->dwCommandFlagsOrStatuses & DOCH_CFSB_PERM_LOCKED)!=0 ) /* OTW protected partition should return wrong key */ +#else /*FL_OTP*/ + if( (partInfoPtr->dwCommandFlagsOrStatuses & (DOCH_CFSB_PERM_LOCKED|DOCH_CFSB_SOTP_LOCKED))==DOCH_CFSB_PERM_LOCKED) /* OTW protected partition should return wrong key */ +#endif /*FL_OTP*/ + { + return flWrongKey; + } + + if( (partInfoPtr->partitionAttributes2&DOCH_PA2B_PROTECTION_TYPE)==DOCH_PARTITION_NOT_PROTECTED) + { + return flNotProtected; + } + + /* password protected */ + if( ((partInfoPtr->partitionAttributes2&DOCH_PA2B_PROTECTION_TYPE)==DOCH_PARTITION_PWD_PROTECTED) || + ((partInfoPtr->partitionAttributes2&DOCH_PA2B_LOCK_CTRL)!=0) ) + { + if( ((partInfoPtr->partitionAttributes2&DOCH_PA2B_GUEST_MODE)==DOCH_PART_ACCESS_MODE_FULL ) && + ((partInfoPtr->partitionAttributes2&DOCH_PA2B_USER_MODE) ==DOCH_PART_ACCESS_MODE_FULL ) ) + {/* both user and guest have full protection -> write protection not applied */ + return flNotProtected; + } + } + +authenticateOnly: + tffsset(dochVol.intermediateBuf, 0, DOCH_SECTOR_SIZE); + tffscpy(pPartitionAcessPassword->bPassword, pKey, wKeyLen); + tffsAPISetIoreq( myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq),DOCH_ACCESS_USER_PASSWORD, 0, dochVol.intermediateBuf, 0,0); + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(myIoreq, bPartNo); + /*Authenticate the partition*/ + rc = flDOCHAccessPartWithPwd(myIoreq); + if (rc != DOCH_OK) + { + return (rc==DOCH_ProtectionFault) ? flWrongKey : TFFS_API_RET(rc); + } + return flOK; +}/* tffsApiAuthPartition() */ + + +#ifndef FL_READ_ONLY +/************************************************************************/ +/* Function name : tffsApiAddOtpIPL*/ +/* Description : adds IPL or OTP partition*/ +/* Return type : static FLStatus - flOK, flGeneralFailure, flHWProtection*/ +/* Argument : FLBoolean bIPL - TRUE, when IPL should be added, FALSE, when OTP*/ +/* Argument : IOreq * myIoreq */ +/************************************************************************/ +static FLStatus tffsApiAddOtpIPL(FLBoolean bIPL, IOreq * myIoreq, IOreq * ioreq) +{ + DOCH_Error rc = DOCH_OK; + FLStatus flStatus; + FLByte * intBuf = dochVol.intermediateBuf; + DOCH_PartitionFormatInfoAPI * pPartitionFormatInfoAPI = (DOCH_PartitionFormatInfoAPI *)intBuf; + + tffsset(intBuf, 0, sizeof(DOCH_PartitionFormatInfoAPI)); + + TFFS_API_SET_MIG_STD_PART_PRMS(pPartitionFormatInfoAPI,0);/* protection type dont matter */ + + /* Protection features */ + pPartitionFormatInfoAPI->dwOtpEnabled = TRUE; /* enable OTP -> IPL can be OTW protected */ + if( bIPL==TRUE ) + { + flStatus = tffsFormatSetProtectionAttribs( CHANGEABLE_PROTECTION|PROTECTABLE, pPartitionFormatInfoAPI, + (FLByte*)DEFAULT_KEY, sizeof(DEFAULT_KEY)); + if( flOK != flStatus ) + return flStatus; + } + else + { + pPartitionFormatInfoAPI->dwProtectionType = DOCH_PARTITION_NOT_PROTECTED; + pPartitionFormatInfoAPI->dwUserAccessMode = DOCH_PART_ACCESS_MODE_FULL; + pPartitionFormatInfoAPI->dwGuestAccessMode = DOCH_PART_ACCESS_MODE_FULL; + } + pPartitionFormatInfoAPI->dwLockControl = DOCH_LOCK_NOT_ACTIVE; + + + /*Partition size (must be FL_LENGTH_IN_BYTES)*/ + pPartitionFormatInfoAPI->nPartitionSize = + (bIPL==TRUE) ? IPL_PARTITION_SIZE_SECTORS : (TFFS_API_OTP_PART_SIZE >> DOCH_SECTOR_SIZE_BITS); + + /*Add partition*/ + tffsAPISetIoreq(myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq), 0,0, intBuf, 0,0); + rc = flDOCHAddPartition(myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("tffsApiAddOtpIPL(): flDOCHAddPartition (IPL) failed with status: 0x%x "), rc)); + return TFFS_API_RET(rc); + } + + /*Retrieve current attributes*/ + tffsset(myIoreq, 0, sizeof(IOreq)); + if( bIPL == TRUE ) + myIoreq->irHandle = FL_GET_SOCKET_FROM_HANDLE(ioreq) + (DOCH_IPL_PARTITION_NUM << 4); + else + myIoreq->irHandle = FL_GET_SOCKET_FROM_HANDLE(ioreq) + (TFFS_API_OTP_PARTITION_NUM << 4); + myIoreq->irData = intBuf; + rc = flDOCHGetParitionUserAttributes(myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("tffsApiAddOtpIPL(): flDOCHGetParitionUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault)? flHWProtection : TFFS_API_RET(rc); + } + + /*Set type to IPL or OTP*/ + ((DOCH_PartitionUserAttrWithBinary*)intBuf)->bType = (bIPL == TRUE) ? PARTITION_TYPE_IPL:PARTITION_TYPE_OTP; + /* set IPL partition to be changeable */ + ((DOCH_PartitionUserAttrWithBinary*)intBuf)->bChangableProtection = bIPL; + /* set IPL partition to be protectable */ + ((DOCH_PartitionUserAttrWithBinary*)intBuf)->bProtected = bIPL; + /*Set attributes back to device*/ + rc = flDOCHSetParitionUserAttributes(myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("tffsApiAddOtpIPL(): flDOCHSetDiskUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault)? flHWProtection : TFFS_API_RET(rc); + } + + tffsAPISetIoreq(myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq), 0,0, intBuf, 0,0); + rc = flDOCHGetDiskUserAttributes(myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("tffsApiAddOtpIPL(): flDOCHGetDiskUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault)? flHWProtection : TFFS_API_RET(rc); + } + + if(bIPL == TRUE) + ((DOCH_DiskUserAttrWithBinary*)intBuf)->bIplPresent = 1; + else + ((DOCH_DiskUserAttrWithBinary*)intBuf)->bOtpPresent = 1; + rc = flDOCHSetDiskUserAttributes(myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("tffsApiAddOtpIPL(): flDOCHSetDiskUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault)? flHWProtection : TFFS_API_RET(rc); + } + return flOK; +}/*tffsApiAddOtpIPL*/ +#endif /*FL_READ_ONLY*/ + +/************************************************************************/ +/* Function name : tffsAPISetIoreq */ +/* Description : */ +/* Return type : IOreq * */ +/* Argument : IOreq * pIoreq*/ +/* Argument : FLHandle irHandle*/ +/* Argument : FLDword irFlags*/ +/* Argument : void* irPath*/ +/* Argument : void * irData*/ +/* Argument : FLSDword irLength*/ +/* Argument : FLSDword irCount*/ +/************************************************************************/ +static IOreq * tffsAPISetIoreq(IOreq * pIoreq, FLHandle irHandle, FLDword irFlags, void* irPath, void * irData, FLSDword irLength, FLSDword irCount) +{ + pIoreq->irCount = irCount; + pIoreq->irData = irData; + pIoreq->irFlags = irFlags; + pIoreq->irHandle = irHandle; + pIoreq->irLength = irLength; + pIoreq->irPath = irPath; + return pIoreq; +}/*tffsAPISetIoreq*/ + +/* end of file tffs_api.c */ + + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/tffs_api.h linux-2.6.30.4/drivers/block/tffs/tffs_api.h --- linux-2.6.30.4-orig/drivers/block/tffs/tffs_api.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/tffs_api.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,224 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following conditions are */ +/* met: */ +/* 1. Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright */ +/* notice, this list of conditions and the following disclaimer in the */ +/* documentation and/or other materials provided with the distribution. */ +/* 3. Neither the name of SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Test for 7.x/src/H3/tffs_api.h-arc $ + * + * Rev 1.32 Dec 11 2007 12:30:54 einat.avidan + * Add format start and format complete signatures in disk user attributes + * + * Rev 1.31 Oct 22 2007 11:34:56 einat.avidan + * update copyrights header + * + * Rev 1.30 Jun 20 2007 12:09:20 einat.avidan + * when DOCH_AUTO_DPD_BY_HOST is enabeled: wrong macro name was used(TFFS_API_IS_DPD_ON instead of TFFS_API_IS_AUTO_DPD_ON) + * + * Rev 1.29 Sep 11 2006 13:45:28 yaniv.iarovici + * Legal header added + * + * Rev 1.28 Aug 16 2006 09:57:50 Yaniv.Iarovici + * Fix compilation error due to PVCS comment + * + * Rev 1.26 Aug 16 2006 08:48:40 Yaniv.Iarovici + * Change OTP partition size to 256KB (#define TFFS_API_OTP_PART_SIZE 0x40000 -> 256KB). + * + * Rev 1.25 Aug 09 2006 17:26:50 Polina.Marimont + * initial for DOC Driver 1.0 + * + * Rev 1.24.1.0 Aug 08 2006 15:55:34 Polina.Marimont + * DOC Driver 1.0 initial + * + * Rev 1.23 Jun 18 2006 13:09:16 Polina.Marimont + * AutoDPD and DPD parameters storage moved to SA SDK + * + * Rev 1.22 Jun 14 2006 18:00:18 Polina.Marimont + * structures definitions moved to this file + * + * Rev 1.21 May 18 2006 09:48:50 polina.marimont + * 1. added function for autoDPD support + * 2. actual partition number API changed + * + * Rev 1.20 Apr 11 2006 13:17:22 tal.heller + * add DOCH_SECURE_DELETE_DATA_OFFSET define + * + * Rev 1.19 Mar 22 2006 17:35:46 DoronC + * Bug fix - add signature to disk attributes in order to use only + * format made by TrueFFS 7.1 and not by host SDK. + * Other format will force reformating of the media. + * + * Rev 1.18 Mar 15 2006 16:18:18 DoronC + * Bug fix - normal IPL of 8KB window was wrong. + * + * Rev 1.17 Mar 15 2006 11:28:18 DoronC + * Bug fix - IPL write was not working properly. + * + * Rev 1.16 Mar 14 2006 09:54:16 DoronC + * Bug fix - IPL size was limited to 1KB when righting normal node + * IPL instead of 2KB + * + * Rev 1.15 Mar 02 2006 08:30:54 DoronC + * Bug fix - IPL was not working since size should be in sectors. + * + * Rev 1.14 Feb 14 2006 10:50:02 DoronC + * Remove large variables from stack. use one global buffer for + * all large buffers needs. + */ + +/***********************************************************************************/ +/* */ +/* Header file for sdk_api module */ +/* */ +/***********************************************************************************/ + +#ifndef _TFFS_API +#define _TFFS_API + +FLStatus bdCallTFFSToDOCH(FLFunctionNo functionNo, IOreq FAR2 *ioreq); + +#ifdef BDK_ACCESS +typedef struct { + FLDword dwStartReadSector; + FLDword dwCurrentReadByte; + FLDword dwReadLength; + FLDword dwStartWriteSector; + FLDword dwCurrentWriteByte; + FLDword dwWriteLength; + FLByte bWriteSubPartitionNum; +} sBdkInitValues; +#endif /*BDK_ACCESS*/ + +typedef struct __DocHVolume +{ + FLMutex mutex; + FLByte numOfBinaryPartitions; + FLByte iplExists; + FLByte otpExists; + FLBoolean verifyWrite; + FLByte *intermediateBuf; + FLDword mountCount[DOCH_MAX_PARTITIONS]; +#ifdef BDK_ACCESS + sBdkInitValues bdkInitValues; +#endif /*BDK_ACCESS*/ + FLDword dwVirtualUnitSize; + FLDword dwVirtualUnitSizeInSectors; + FLDword dwNumOfUnits; + FLDword dwUnformattedCapacity; + + FLDword dwPowerMode[FL_SOCKETS]; /* saves power modes */ +}DocHVolume; + +/* MACRO: TFFS_API_IS_AUTO_DPD_ON - determines whether one of Auto DPD modes defined */ +#define TFFS_API_IS_AUTO_DPD_ON(socket) ( ((gDpdSettings.activeMode & DOCH_WM_NORMAL_AND_AUTO_STBY) == DOCH_WM_NORMAL_AND_AUTO_STBY) || \ + ((gDpdSettings.activeMode & DOCH_WM_LOW_FREQ_AND_AUTO_STBY) == DOCH_WM_LOW_FREQ_AND_AUTO_STBY) || \ + ((gDpdSettings.inActiveMode & DOCH_IM_IDLE_2_DPD) == DOCH_IM_IDLE_2_DPD) ) +/* MACRO: TFFS_API_SAVE_DPD_STATES(socket) - saves the power modes into global variable */ +#define TFFS_API_SAVE_POWER_MODES(socket) dochVol.dwPowerMode[socket] = gDpdSettings.inActiveMode | gDpdSettings.activeMode; + +/********************/ +/* Defines */ +/********************/ + +#define DOCH_SECTORS_IN_UNIT_BITS 9 +#define DOCH_SECTORS_IN_UNIT (1< + + +/* + * macro + */ + +#define Align(ptr,alignment) (((unsigned long)(ptr)) & (~((alignment) - 1))) + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) && !defined(virt_addr_valid) +# define virt_addr_valid(vaddr) (((vaddr) >= PAGE_OFFSET) && ((vaddr) < (unsigned long)high_memory)) +#endif + + +/* + * static routines + */ +static void __dmasw_bread (int off, void *vbuf, unsigned int bytes); +static void __dmasw_bwrite (int off, void *vbuf, unsigned int bytes); + + + + +/*-----------------------------------------------------------------------* + * * + * t f f s _ d m a s w * + * * + * Transfer data between DiskOnChip's and RAM buffer. * + * This routines handles any kind of virtual buffer (linearly mapped or * + * vmalloc() allocated, spanning multiple memory pages, containing * + * multiple sectors). * + * * + * Parameters: * + * win pointer to DiskOnChip's I/O window * + * off offset of DiskOnChip's I/O register from the base * + * of DiskOnChip window * + * vbuf virtual address of RAM buffer * + * bytes bytes to transfer * + * read DMA direction: '1' for DiskOnChip->RAM, or zero * + * for RAM->DiskOnChip * + * * + *-----------------------------------------------------------------------*/ + +void tffs_dmasw ( char * win, + int off, + void * vbuf, + unsigned int bytes, + int read ) +{ + /* We check if 'vbuf' is linearly mapped kernel virtual address (and + * is therefore laid out in consecutive physical pages). If 'vbuf' + * is not linearly mapped (i.e. came from user space or allocated + * via vmalloc()), we check if it entirely fits into a single memory + * page. + */ + if ((virt_addr_valid((unsigned long)vbuf)) /* linearly mapped kernel virtual address */ + || + (Align(vbuf,PAGE_SIZE) == Align((unsigned long)vbuf + bytes,PAGE_SIZE))) + { + if (read == 1) + __dmasw_bread (off, vbuf, bytes); + else + __dmasw_bwrite (off, vbuf, bytes); + } + else /* 'vbuf' crosses memory page boundary */ + { + if (bytes >= (FL_SECTOR_SIZE * 2)) /* two or more sectors */ + { + register unsigned long bytes_on_this_page; + + /* Do multiple DMA transfers, each one fitting into a single + * memory page. + */ + do + { + bytes_on_this_page = PAGE_SIZE - ((unsigned long)vbuf & (PAGE_SIZE - 1)); + if (bytes_on_this_page > bytes) + bytes_on_this_page = bytes; + + if (read == 1) + __dmasw_bread (off, vbuf, bytes_on_this_page); + else + __dmasw_bwrite (off, vbuf, bytes); + + bytes -= bytes_on_this_page; + vbuf = (char *)vbuf + bytes_on_this_page; + + } while (bytes > 0); + } + else /* single sector; don't bother with DMA ... */ + { + if (read == 1) + tffs_readw ((unsigned long)(win + off), vbuf, (bytes / sizeof(short))); + else + tffs_writew ((unsigned long)(win + off), vbuf, (bytes / sizeof(short))); + } + } +} + + + + + +#if defined(CONFIG_ARCH_MAINSTONE) || defined(CONFIG_MACH_MAINSTONE) + +/*_____________________________________________________________________________ + | | + | | + | Intel PXA27x ("Mainstone") board | + | | + |____________________________________________________________________________| +*/ + + +# include +# include +# include + + +/* Routine blk_dma_inv_range_harvard() (arch/arm/mm/blockops.c) appears + * to be buggy: it seems to constantly shoot past the end of the address + * range [vbuf..vbuf+bytes] by 32 bytes. It also appears to write some + * bogus data into this RAM address range while invalidating it in D-cache. + */ +# define PXA27X_DCACHE_BUG_WORKAROUND + + +/* + * static routines for PXA27x + */ + +static void tffs_dma_init (int resume); +static void tffs_dma_release (void); +static void tffs_dma_intr (int dma, void *dummy); + + + + +/*-----------------------------------------------------------------------* + * * + * t f f s a r c h _ i n i t * + * * + * This routine is called during module initialization time with 'resume'* + * argument set to FALSE, and from Power Manager's 'resume' routine with * + * 'resume' argument set to TRUE. If 'resume' is FALSE, this routine * + * allocates and initializes all required board resources; if 'resume' * + * is TRUE, this routine does minimal required re-initialization of * + * these resources after power suspend. * + * * + * Parameters: * + * suspend FALSE (module initialization) or TRUE (power resume) * + * * + * Returns: * + * always '1' (success) * + * * + *-----------------------------------------------------------------------*/ + +unsigned char tffsarch_init ( int resume ) +{ + /* chip select that DiskOnChip is connected to */ +#define PXA27X_CS 5 + + /* Value to write to chip select's conf register. Possible values are: + * + * 0x099C VLIO DiskOnChip adapter and DiskOnChip G4/G3/H3 device + * 0x0AAC VLIO DiskOnChip adapter and DiskOnChip H1 device + * 0xA998 sync DiskOnChip adapter and DiskOnChip G4/G3/H3 device + * 0xAAA8 sync DiskOnChip adapter and DiskOnChip H1 device + * + * Register description: + * + * 31 0 - slow device (VLIO); 1 - fast device + * 30:28 The value of this bit is half the number of memory clock cycles + * from the time that chip select is de-asserted after a read or + * write until the next chip select (of a different static memory + * bank) or nSDCS is asserted + * 27:24 ROM Delay Next Access The RDN field is encoded as follows: + * ENCODED (Programmed) Value -----> DECODED (Actual) Value + * 0-11 -----> 0-11 + * 12 -----> 15 + * 13 -----> 20 + * 14 -----> 26 + * 15 -----> 30 + * RDNx * 2 = amount of time nOE or nPWE is deasserted to address + * hold and address setup to nOE or nPWE assertion time + * 23:20 This determines the minimum number of memory clock cycles + * (minus 1) of nOE (nPWE) assert time for each beat of read (write) + * 19 ROM Bus Width (1 = 16 bits) + * 16-18 0 - Synchronous flash; 2 - burst 4; 3 - burst 8; 4 - Variable-latency + * I/O (VLIO) + */ + +#define PXA27X_CS_VAL 0x026C /* andrayk Nov 242 006: originally was 0x044C */ + + int cs = PXA27X_CS; + unsigned long val; + + if (resume == FALSE) + { PrintkInfo ("use Chip Select %d", cs); } + + /* Line below configures GPIO33 as output. + * Without this line, DiskOnChip driver fails to detect DiskOnChip G4. + */ + GPDR1 |= 0x2; /* was: GPDR1 = 0xfc3fab83 */ + + /* read chip select config reg */ + val = __REG(0x48000008 + ((cs / 2) * sizeof(long))); + + if (cs & 1) + val = ((PXA27X_CS_VAL << 16) | (val & 0xffff)); + else + val = ((val & 0xffff0000) | PXA27X_CS_VAL); + + /* write chip select config reg */ + __REG(0x48000008 + ((cs / 2) * sizeof(long))) = val; + + /* if DMA is requested, configure it */ + if (tffs_dma_mode > 0) + { + tffs_dma_init (resume); + } + + return 1; +} + + + +void TffsHWRelease(void) +{ + /* if DMA was actually used, release all DMA resources */ + if (tffs_dma_mode > 0) + { + tffs_dma_release (); + } +} + + + + +/*-----------------------------------------------------------------------* + * * + * t f f s _ d m a _ i n i t * + * * + * This routine is called during module initialization time with 'resume'* + * argument set to FALSE, and from Power Manager's 'resume' routine with * + * 'resume' argument set to TRUE. If 'resume' is FALSE, this routine * + * allocates and initializes all required DMA resources; if 'resume' is * + * TRUE, this routine does minimal required re-initialization of DMA * + * channel after power suspend. * + * * + * Parameters: * + * resume FALSE (module initialization) or TRUE (power resume) * + * * + *-----------------------------------------------------------------------*/ +static +void tffs_dma_init (int resume) +{ + if (resume == FALSE) + { + /* We use single DMA channel for both 'read' and + * 'write' operations, so we allocate it here. + */ + if ((tffsInfo.channel = pxa_request_dma(TFFS_DEVICE_NAME, + DMA_PRIO_LOW, tffs_dma_intr, NULL)) < 0) + { + /* failed to allocate DMA channel, won't use DMA */ + tffs_dma_mode = 0; + + PrintkError ("can't get DMA chan"); + return; + } + PrintkInfo ("use DMA channel %d", tffsInfo.channel); + } + + DRCMR(tffsInfo.channel) = (DRCMR_MAPVLD | (tffsInfo.channel & 0x1f)); + __REG(0x400000a0) |= (1 << tffsInfo.channel); + + /* clear any pending DMA errors/interrupts */ + DCSR(tffsInfo.channel) = (DCSR_NODESC | DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR); + + if (resume == FALSE) + { + tffsInfo.dma_buf_vptr = NULL; + tffsInfo.dma_buf_size = 0; + + if ((tffs_dma_mode >= 1) +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) || !defined(PXA27X_DCACHE_BUG_WORKAROUND) + && (tffs_dma_mode <= 3) +#endif + ) + { + /* allocate intermediate DMA buffer (we assume one MMU page will be enough) */ + tffsInfo.dma_buf_size = PAGE_SIZE; + + tffsInfo.dma_buf_vptr = +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + consistent_alloc ((GFP_KERNEL | GFP_DMA), tffsInfo.dma_buf_size, + &tffsInfo.dma_buf_paddr); +#else + dma_alloc_coherent (NULL, tffsInfo.dma_buf_size, + &tffsInfo.dma_buf_paddr, (GFP_KERNEL | GFP_DMA)); +#endif + if (tffsInfo.dma_buf_vptr == NULL) + { + /* failed to allocate intermediate DMA buffer, won't use DMA */ + tffs_dma_mode = 0; + + pxa_free_dma (tffsInfo.channel); + + tffsInfo.channel = -1; + tffsInfo.dma_buf_size = 0; + + PrintkError ("can't alloc DMA buffer, won't use DMA"); + } + } + } +} + + + +/*-----------------------------------------------------------------------* + * * + * t f f s _ d m a _ r e l e a s e * + * * + * Release all previously allocated DMA resources (channel, intermediate * + * DMA buffer etc.). For Intel PXA27x (Mainstone) board. * + * * + *-----------------------------------------------------------------------*/ + +static +void tffs_dma_release(void) +{ + /* if previously was allocated, release DMA channel */ + if (tffsInfo.channel >= 0) + { + pxa_free_dma (tffsInfo.channel); + + tffsInfo.channel = -1; + } + + /* if previously was allocated, release intermediate DMA buffer */ + if (tffsInfo.dma_buf_vptr != NULL) + { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + consistent_free (tffsInfo.dma_buf_vptr, PAGE_SIZE, tffsInfo.dma_buf_paddr); +#else + dma_free_coherent (NULL, PAGE_SIZE, tffsInfo.dma_buf_vptr, tffsInfo.dma_buf_paddr); +#endif + tffsInfo.dma_buf_vptr = NULL; + } +} + + + + +/*-----------------------------------------------------------------------* + * * + * _ _ d m a s w _ b r e a d * + * * + * Transfer data from DiskOnChip's I/O reguster to RAM buffer. * + * Example implementation For Intel PXA27x (Mainstone) board. * + * * + * Parameters: * + * off offset of DiskOnChip's I/O register from the base * + * of DiskOnChip window * + * vbuf virtual address of RAM buffer * + * bytes bytes to transfer * + * * + *-----------------------------------------------------------------------*/ +static +void __dmasw_bread ( int off, + void * vbuf, + unsigned int bytes ) +{ + int chan = tffsInfo.channel; + u_int tmp; + register int waiting; + register int direct_dma; + + profiling[2]++; + + direct_dma = ((tffs_dma_mode & 4) ? TRUE : FALSE); + + /* Due to a bug in kernel routine blk_dma_inv_range_harvard() + * (arch/arm/mm/blockops.c), we allow direct DMA to destination + * buffer 'vbuf' only when it's aligned at CPU's cache line boundary. + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) && defined(PXA27X_DCACHE_BUG_WORKAROUND) + if ((u32)vbuf & 31) + direct_dma = FALSE; +#endif + + /* Set source physical address for DMA transfer (this would be DiskOnChip's + * I/O register which is located at offset 'off' from the DiskOnChip's + * base address as specified by tffs_addr[0]). + */ + DSADR(chan) = tffs_addr[0] + off; + + /* Set target physical address for DMA transfer. + * This would be physical address of intermediate DMA buffer (for + * DMA modes 1/2/3), or physical address of the destination buffer + * (for DMA modes 5/6/7). + */ + if (direct_dma == TRUE) /* do DMA transfer directly into 'vbuf' */ + { + if (virt_addr_valid((unsigned long)vbuf)) /* 'vbuf' is in low memory */ + { + DTADR(chan) = __pa (vbuf); + } + else /* 'vbuf' is in high memory */ + { + char * k_vbuf = (char *) page_address(vmalloc_to_page(vbuf)) + + ((unsigned long)vbuf & (PAGE_SIZE - 1)); + if (k_vbuf == NULL) + { + PrintkError ("error, DMA requested on high memory page"); + return; + } + + DTADR(chan) = __pa (k_vbuf); + + /* andrayk Nov 22 2006: possible bug. Routine consistent_alloc() + * (arch/arm/mm/consistent.c) applies __pa() macro to it's 'vbuf' + * argument (see below). This might cause CPU exception. + */ + } + + /* Write (if dirty) and purge contents of 'vbuf' from CPU cache(s) */ + /* Possible options: + * consistent_sync(vbuf, bytes, DMA_FROM_DEVICE); ARM/SH + * dma_cache_inv((unsigned long)vbuf, (unsigned long)bytes); MIPS/PPC/x86 + */ + +#ifdef PXA27X_DCACHE_BUG_WORKAROUND + + /* Routine blk_dma_inv_range_harvard() (arch/arm/mm/blockops.c) appears + * to be buggy: it seems to constantly shoot past the end of the address + * range [vbuf..vbuf+bytes] by 32 bytes. It also appears to write some + * bogus data into this RAM address range while invalidating it in D-cache. + */ + consistent_sync (vbuf, bytes - 1, DMA_FROM_DEVICE); +#else + consistent_sync (vbuf, bytes, DMA_FROM_DEVICE); +#endif + } + else /* transfer into intermediate DMA buffer */ + { + DTADR(chan) = tffsInfo.dma_buf_paddr; + } + + /* specify parameters of DMA transfer */ + tmp = DCMD_INCTRGADDR | /* increment target address */ + DCMD_WIDTH2 | /* 16-bit data path */ + /* DCMD_ENDIRQEN | */ /* don't generate interrupt at the end of transfer */ + bytes; + + if ((bytes & 31) == 0) + tmp |= DCMD_BURST32; /* 32-bytes burst */ + + DCMD(chan) = tmp; + + /* clear all status bits, and start DMA transfer */ + DCSR(chan) = (DCSR_RUN | DCSR_NODESC | DCSR_ENDINTR | DCSR_STOPSTATE | DCSR_BUSERR); + + /* poll DMA channel's status register for end of DMA transfer */ + for (waiting = 100000; waiting > 0; waiting--) /* hope this is long enough ... */ + { + /* read Channel Status Register to find out status of DMA transfer */ + tmp = DCSR (chan); + + if (tmp & (DCSR_STOPSTATE | DCSR_BUSERR)) + { + if ((tmp & DCSR_BUSERR) == 0) + { + /* DMA transfer completed, move data from the intermediate DMA + * buffer to the destination buffer (in case it was used). + */ + if (direct_dma == FALSE) + memcpy (vbuf, tffsInfo.dma_buf_vptr, bytes); + } + else + { + PrintkError ("Bus error, DMA transfer failed"); + /* andrayk Mar 24 2006: DMA transfer failed, find way to let MTD know this */ + } + return; + } + } + + PrintkError ("DMA transfer timed out"); +} + + + + +/*-----------------------------------------------------------------------* + * * + * _ _ d m a s w _ b w r i t e * + * * + * Transfer data from RAM buffer to DiskOnChip's I/O reguster. * + * Example implementation for Intel PXA27x (Mainstone) board. * + * * + * Parameters: * + * off offset of DiskOnChip's I/O register from the base * + * of DiskOnChip window * + * vbuf virtual address of RAM buffer * + * bytes bytes to transfer * + * * + *-----------------------------------------------------------------------*/ +static +void __dmasw_bwrite ( int off, + void * vbuf, + unsigned int bytes ) +{ + int chan = tffsInfo.channel; + u_int tmp; + register int waiting; + + profiling[3]++; + + /* Set target physical address for DMA transfer (this would be DiskOnChip's + * I/O register which is located at offset 'off' from the DiskOnChip's + * base address as specified by tffs_addr[0]). + */ + DTADR(chan) = tffs_addr[0] + off; + + /* set source physical address for DMA transfer */ + + if (tffs_dma_mode & 4) /* do DMA transfer directly from 'vbuf' */ + { + /* Write (if dirty) contents of 'vbuf' from CPU D-cache to RAM. + * Possible options: + * consistent_sync(vbuf, bytes, DMA_TO_DEVICE); ARM/SH + * dma_cache_wback((unsigned long)vbuf, (unsigned long)bytes); MIPS/PPC/x86 + */ + consistent_sync (vbuf, bytes, DMA_TO_DEVICE); + + if (virt_addr_valid((unsigned long)vbuf)) /* 'vbuf' is in low memory */ + { + DSADR(chan) = __pa (vbuf); + } + else /* 'vbuf' is in high memory */ + { + char * k_vbuf = (char *) page_address(vmalloc_to_page(vbuf)) + + ((unsigned long)vbuf & (PAGE_SIZE - 1)); + if (k_vbuf == NULL) + { + PrintkError ("error, DMA requested on high memory page"); + return; + } + + DSADR(chan) = __pa (k_vbuf); + } + } + else /* use intermediate DMA buffer */ + { + /* move data from RAM buffer to the intermediate DMA buffer */ + memcpy (tffsInfo.dma_buf_vptr, vbuf, bytes); + + DSADR(chan) = tffsInfo.dma_buf_paddr; + } + + /* specify parameters of DMA transfer */ + tmp = DCMD_INCSRCADDR | /* increment source address */ + DCMD_WIDTH2 | /* 16-bit data path */ + /* DCMD_ENDIRQEN | */ /* don't generate interrupt at the end of transfer */ + bytes; + + if ((bytes & 31) == 0) + tmp |= DCMD_BURST32; /* 32-bytes burst */ + + DCMD(chan) = tmp; + + /* clear all status bits, and start DMA transfer */ + DCSR(chan) = (DCSR_RUN | DCSR_NODESC | DCSR_ENDINTR | DCSR_STOPSTATE | DCSR_BUSERR); + + /* poll DMA channel's status register for end of DMA transfer */ + for (waiting = 100000; waiting > 0; waiting--) /* hope this is long enough ... */ + { + /* read Channel Status Register to find out status of DMA transfer */ + tmp = DCSR (chan); + + if (tmp & (DCSR_STOPSTATE | DCSR_BUSERR)) + { + if (tmp & DCSR_BUSERR) + { + PrintkError ("Bus error, DMA transfer failed"); + /* andrayk Mar 24 2006: DMA transfer failed, find way to let MTD know this */ + } + else + { + /* DMA transfer successful */ + } + return; + } + } + + PrintkError ("DMA transfer timed out"); +} + + + + +/*-----------------------------------------------------------------------* + * * + * t f f s _ d m a _ i n t r * + * * + * Handle DMA interrupt on Intel PXA27x (Mainstone) board. * + * * + * Parameters: * + * dma interrupting DMA channel * + * dummy not used * + * regs not used * + * * + *-----------------------------------------------------------------------*/ +static +void tffs_dma_intr ( int dma, + void * dummy) /* not used */ +{ + register u_int tmp; + + profiling[4]++; + + /* check if interrupt came from our DMA channel */ + if (dma == tffsInfo.channel) + { + /* check if DMA transfer was successful */ + if ((tmp = DCSR(dma)) & DCSR_BUSERR) + { + /* andrayk Mar 24 2006: DMA transfer failed, find way to let MTD know this */ + PrintkError ("Bus error, DMA transfer failed"); + } + + /* clear DMA interrupt from this channel */ + DCSR(dma) = (tmp | (DCSR_BUSERR | DCSR_ENDINTR)); + } + else + { PrintkError ("received DMA interrupt on wrong channel"); } +} + + + + +#elif defined(CONFIG_OMAP_H2) || defined(CONFIG_MACH_OMAP_H2) + +/*_____________________________________________________________________________ + | | + | | + | Texas Instruments OMAP-1610 (H2) board | + | | + |____________________________________________________________________________| +*/ + +# include +# include + + /* + + EMIFS: Extended Memory Interface Slow. This 16-bit wide bus can interface + with and handle all transactions to flash memory, ROM, asynchronous + memories, and synchronous burst flash. + The EMIFS can support 16-bit interface width only. + TC: traffic controller + The EMIFS supports 8-,16-, or 32-bit asynchronous and synchronous + read, 4- x 32-bit synchronous burst read and 8-, 16-, or 32-bit + asynchronous write. + + EMIFS_PRIOR EMIFS LRU priority register FFFECC04 + EMIFS_CONFIG EMIFS configuration register FFFECC0C + EMIFS_CCS2 EMIFS chip-select configuration CS2 FFFECC18 + 7:4 RDWST Controls the wait states cycle number for asynchronous read operation and the initial idle time for asynchronous read page mode and synchronous read mode. + 15:12 PGWST/WELEN Controls the wait states cycle number between accesses in a page for asynchronous page mode. Controls the WE pulse length during a write access. When PGWSTEN is 0, this bit specifies both PGWST/WELEN. When PGWSTEN is 1, this bit specifies only WELEN + EMIFS_PTOR1 EMIFS dynamic priority time-out 1 FFFECC28 + EMIFS_PTOR2 EMIFS dynamic priority time-out 2 FFFECC2C + EMIFS_PTOR3 EMIFS dynamic priority time-out 3 FFFECC30 + EMIFS_DWS EMIFS dynamic wait states FFFECC40 + EMIFS_AADDR EMIFS abort address FFFECC44 + EMIFS_ATYPER EMIFS abort type FFFECC48 + EMIFS_ATOR EMIFS abort time-out FFFECC4C + EMIFS_ACS2 Advanced EMIFS chip-select configuration nCS2 FFFECC58 + + + EMIFS_CS2_CONFIG 0xFFFECC18 + BSP sets the reg val 0xf800f22a, but the val after kernel starts is 0xff80fff3 + + */ + + + + +/* + * static routines for OMAP1610 + */ + +static void tffs_dma_init (int resume); +static void tffs_dma_release (void); + + + +/* + * static vars + */ + +static dma_regs_t * dma_regs = NULL; + + + +/*-----------------------------------------------------------------------* + * * + * t f f s a r c h _ i n i t * + * * + * This routine is called during module initialization time with 'resume'* + * argument set to FALSE, and from Power Manager's 'resume' routine with * + * 'resume' argument set to TRUE. If 'resume' is FALSE, this routine * + * allocates and initializes all required board resources; if 'resume' * + * is TRUE, this routine does minimal required re-initialization of * + * these resources after power suspend. * + * * + * Parameters: * + * suspend FALSE (module initialization) or TRUE (power resume) * + * * + * Returns: * + * always '1' (success) * + * * + *-----------------------------------------------------------------------*/ + +unsigned char tffsarch_init (int resume) +{ + register unsigned short tmp16; + register unsigned long tmp32; + + /* Configure Chip Select that DiskOnChip is connected to. + * + * NOTE. Code below configures Chip Select to set duration of + * DiskOnChip access cycle to 70 nanosecond, which is + * appropriate for the case when DiskOnChip is connected to + * OMAP1610 board via M-Systems' adapters. If you solder + * DiskOnChip into your board, consider changing Chip Select + * settings to significantly shorten DiskOnChip acecss cycle. + * This should have significant positive efefct on + * DiskOnChip's 'read' performance. + */ + tmp32 = (1 << 27) | /* wait states between accesses in a page for async. page mode */ + (1 << 23) | /* idle cycles for bus turn around */ + (0 << 16) | /* asynchronous read */ + (1 << 12) | /* WE length */ + (0 << 8) | /* wait states in write operation */ + (0 << 4) | /* wait states in read operation */ + 2; /* REF_CLK = TC_CK / 2 */ + +#define OMAP1610_H2_CS 2 /* chip select that DiskOnChip is connected to */ + + outl (tmp32, (EMIFS_CS0_CONFIG + (OMAP1610_H2_CS * sizeof(unsigned long)))); + + if (tffs_irq >= 0) + { + /* Configure GPIO-9 as input. This is actually a default state + * after reset, but just to be sure ... + */ + tmp16 = inw (GPIO_DIRECTION_REG); + outw ((tmp16 | (1 << (tffs_irq - IH_GPIO_BASE))), GPIO_DIRECTION_REG); + + /* configure DiskOnChip IRQ as GPIO-9, disable PullDown */ + outl( (inl(PULL_DWN_CTRL_2) | (1 << 23)), PULL_DWN_CTRL_2); + + /* select function W8 pin as GPIO-9 */ + outl( (inl(FUNC_MUX_CTRL_B) & 0xFF1FFFFF), FUNC_MUX_CTRL_B); + } + +# if 0 + volatile unsigned long*reg; + unsigned long ulTemp; + + /* configure DMAREQ# as MPUIO4, disable PullDown */ + ulTemp = *(volatile unsigned long*) 0xFFFE1044; + ulTemp |= 0x00002000; /* 0x1<<13; */ + *(volatile unsigned long *)0xFFFE1044 = (unsigned long)ulTemp; + + /* select function DMA_REQ tffsInfo.channel 6 */ + ulTemp = *(volatile unsigned long*) 0xFFFE1020; + ulTemp |= 0x8000; /* 0x1<<15; */ + *(volatile unsigned long *)0xFFFE1020 = (unsigned long)ulTemp; + + /* configure mDoc IRQ# as GPIO-9, disable PullDown */ + /* TH: For H2 Platform */ + ulTemp = *(volatile unsigned long*) 0xFFFE1048; + ulTemp |= 0x800000; /* 0x1<<23; */ + *(volatile unsigned long *)0xFFFE1048 = (unsigned long)ulTemp; + + /* select function W8 pin as GPIO-9 */ + ulTemp = *(volatile unsigned long*) (0xFFFE1030); + ulTemp &= 0xFF1FFFFF; + *(volatile unsigned long *)(0xFFFE1030) = (unsigned long)ulTemp; + + reg=(unsigned long*)EMIFS_CONFIG_REG; + PrintkInfo("EMIFS_CONFIG_REG=0x%lx",*reg); + *reg=0x0c; + reg=(unsigned long*)EMIFS_CONFIG_REG; + PrintkInfo("EMIFS_CONFIG_REG=0x%lx",*reg); + + reg=(unsigned long*)EMIFS_CS2_CONFIG2; + PrintkInfo("EMIFS_CS2_CONFIG2=0x%lx",*reg); + + reg=(unsigned long*)EMIFS_CS2_CONFIG; + PrintkInfo("EMIFS_CS2_CONFIG=0x%lx",*reg); + *reg=0x8070; + reg=(unsigned long*)EMIFS_CS2_CONFIG; + PrintkInfo("EMIFS_CS2_CONFIG=0x%lx",*reg); +# endif + + /* if DMA is requested, configure it */ + if (tffs_dma_mode > 0) + { + tffs_dma_init (resume); + } + + return 1; +} + + + +void TffsHWRelease(void) +{ + /* if DMA was actually used, release all DMA resources */ + if (tffs_dma_mode > 0) + { + tffs_dma_release (); + } +} + + +/*-----------------------------------------------------------------------* + * * + * t f f s _ d m a _ i n i t * + * * + * This routine is called during module initialization time with 'resume'* + * argument set to FALSE, and from Power Manager's 'resume' routine with * + * 'resume' argument set to TRUE. If 'resume' is FALSE, this routine * + * allocates and initializes all required DMA resources; if 'resume' is * + * TRUE, this routine does minimal required re-initialization of DMA * + * channel after power suspend. * + * * + * Parameters: * + * resume FALSE (module initialization) or TRUE (power resume) * + * * + *-----------------------------------------------------------------------*/ +static +void tffs_dma_init (int resume) +{ + u32 tmp; + + if (resume == FALSE) + { + /* We use single DMA channel for both 'read' and 'write' operations, + * so we allocate it here. We don't use DMA interrupts, so we won't + * need DMA callback. + */ + tffsInfo.channel = + omap_request_dma (eDMANotSync, /* not connected to any DMA line */ + TFFS_DEVICE_NAME, + NULL, /* no callback when DMA completes */ + NULL, /* data to pass to DMA callback */ + &dma_regs); + if ((tffsInfo.channel != 0) || (dma_regs == NULL)) + { + /* failed to allocate DMA channel, won't use DMA */ + tffs_dma_mode = 0; + + PrintkError ("can't get DMA chan"); + return; + } + } + + /* Logical Channel Control Register. + * Specify peripheral DMA transfer. + */ + dma_regs->lch_ctrl = LCH_TYPE_P; + + /* Channel Element Number Register. + * Specify single element (16-bit word) per DMA frame. + */ + dma_regs->cen = 1; + + /* Channel Control Register 2. + * Specify block synchronization. + */ + dma_regs->ccr2 = (1 << 2); + + /* Channel Interrupt Control Register. + * Enable time-out interrupt, disable all others. + */ + dma_regs->cicr = /* (1 << 5) | */ /* end-of-block interrupt */ + 1; /* timeout interrupt */ + + /* read Channel Status register to clear it */ + tmp = dma_regs->csr; + + if (resume == FALSE) + { + tffsInfo.dma_buf_vptr = NULL; + tffsInfo.dma_buf_size = 0; + + if ((tffs_dma_mode >= 1) && (tffs_dma_mode <= 3)) + { + /* allocate intermediate DMA buffer (we assume one MMU page will be enough) */ + tffsInfo.dma_buf_size = PAGE_SIZE; + + tffsInfo.dma_buf_vptr = +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + consistent_alloc ((GFP_KERNEL | GFP_DMA), tffsInfo.dma_buf_size, + &tffsInfo.dma_buf_paddr); +#else + dma_alloc_coherent (NULL, tffsInfo.dma_buf_size, + &tffsInfo.dma_buf_paddr, (GFP_KERNEL | GFP_DMA)); +#endif + if (tffsInfo.dma_buf_vptr == NULL) + { + /* failed to allocate intermediate DMA buffer, won't use DMA */ + tffs_dma_mode = 0; + + omap_free_dma (dma_regs); + dma_regs = NULL; + + tffsInfo.dma_buf_size = 0; + PrintkError ("can't alloc DMA buffer"); + } + } + } +} + + + + +/*-----------------------------------------------------------------------* + * * + * t f f s _ d m a _ r e l e a s e * + * * + * Release all previously allocated DMA resources (channel, intermediate * + * DMA buffer etc.). For OMAP1610 (H2) board. * + * * + *-----------------------------------------------------------------------*/ +static +void tffs_dma_release(void) +{ + /* if previously was allocated, release DMA channel */ + if (tffsInfo.channel == 0) + { + omap_free_dma (dma_regs); + dma_regs = NULL; + + tffsInfo.channel = -1; + } + + /* if previously was allocated, release intermediate DMA buffer */ + if (tffsInfo.dma_buf_vptr != NULL) + { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + consistent_free (tffsInfo.dma_buf_vptr, PAGE_SIZE, tffsInfo.dma_buf_paddr); +#else + dma_free_coherent (NULL, PAGE_SIZE, tffsInfo.dma_buf_vptr, tffsInfo.dma_buf_paddr); +#endif + tffsInfo.dma_buf_vptr = NULL; + } +} + + + + +/*-----------------------------------------------------------------------* + * * + * _ _ d m a s w _ b r e a d * + * * + * Transfer data from DiskOnChip's I/O reguster to RAM buffer. * + * Example implementation For Texas Instruments OMAP1610 H2 board. * + * * + * Parameters: * + * off offset of DiskOnChip's I/O register from the base * + * of DiskOnChip window * + * vbuf virtual address of RAM buffer * + * bytes bytes to transfer * + * * + *-----------------------------------------------------------------------*/ +static +void __dmasw_bread ( int off, + void * vbuf, + unsigned int bytes ) +{ + register u32 tmp; + register int waiting; + + profiling[2]++; + + /* Channel Source/Destination Parameters. + * Specify 16-bit port width, EMIFS source, allow source packing, + * 4-words burst allowed for source, EMIFF destination. allow + * destination packing, 4-words burst allowed for destination. + */ + dma_regs->csdp = (BURST_4 << 14) | /* dest.: use 4-word burst */ + DCSDP_DST_PACK | /* pack dest. */ + (PORT_EMIFF << 9) | /* dest. is EMIFF (RAM) */ + (BURST_4 << 7) | /* source: use 4-word burst */ + DCSDP_SRC_PACK | /* pack source */ + (PORT_EMIFS << 2) | /* source is EMIFS (DiskOnChip) */ + DATA_TYPE_S16; /* 16-bit data path */ + + /* Channel Control Register. + * Specify no synchronization, no OMAP 3.0/3.1 compatibility, no + * frame synchronization, high priority, constant source address, + * post-increment destination address. + */ + dma_regs->ccr = (AMODE_POST_INC << 14) | /* dest (RAM): post-increment */ + (AMODE_CONST << 12) | /* source (DiskOnChip) : const addr. */ + DCCR_N31COMP | /* no OMAP 3.0/3.1 compatibility */ + DCCR_PRIO; /* high priority */ + + /* Channel Frame Number Register. + * We assume that frame consists of single element, and element + * consists of single 16-bit word. + */ + dma_regs->cfn = (bytes / sizeof(u16)); + + /* Channel Source Start Address Registers. This would be DiskOnChip's + * I/O register which is located at offset 'off' from the DiskOnChip's + * base address as specified by tffs_addr[0]). + */ + tmp = tffs_addr[0] + off; + dma_regs->cssa_u = (tmp >> 16); + dma_regs->cssa_l = (tmp & 0xffff); + + /* Channel Destination Start Address Registers */ + if (tffs_dma_mode & 4) /* do DMA transfer directly into 'vbuf' */ + { + if (virt_addr_valid((unsigned long)vbuf)) /* 'vbuf' is in low memory */ + { + tmp = __pa (vbuf); + } + else /* 'vbuf' is in high memory */ + { + char * k_vbuf = (char *) page_address(vmalloc_to_page(vbuf)) + + ((unsigned long)vbuf & (PAGE_SIZE - 1)); + tmp = __pa (k_vbuf); + } + + /* write (if dirty) and purge contents of 'vbuf' from CPU cache(s) */ +#if 1 + /* D-cache only. Possible options: + * flush_dcache_range((unsigned long)vbuf, (unsigned long)(vbuf + bytes)); ARM/PPC + * consistent_sync(vbuf, bytes, PCI_DMA_BIDIRECTIONAL); ARM/PPC + * dma_cache_wback_inv((unsigned long)vbuf, (unsigned long)bytes); MIPS/PPC/SH/x86 + */ + flush_dcache_range ((unsigned long)vbuf, (unsigned long)(vbuf + bytes)); +#else + /* both D- and I-caches */ + cpu_cache_clean_invalidate_range ((unsigned long)vbuf, (unsigned long)(vbuf + bytes), 1); +#endif + } + else /* transfer into intermediate DMA buffer */ + { + tmp = tffsInfo.dma_buf_paddr; + } + dma_regs->cdsa_u = (tmp >> 16); + dma_regs->cdsa_l = (tmp & 0xffff); + + /* start DMA channel */ + dma_regs->ccr |= DCCR_EN; + + /* wait for DMA transfer to finish */ + for (waiting = 100000; waiting > 0; waiting--) /* hope this is long enough ... */ + { + if (((tmp = dma_regs->ccr) & DCCR_EN) == 0) + { + /* read Channel Status Register to clear it */ + if (((tmp = dma_regs->csr) & DCSR_ERROR) == 0) + { + /* DMA transfer completed, move data from the intermediate DMA + * buffer to the destination buffer (in case it was used). + */ + if ((tffs_dma_mode & 4) == 0) + memcpy (vbuf, tffsInfo.dma_buf_vptr, bytes); + } + else /* andrayk June 13 2006: DMA transfer failed, find way to let MTD know this */ + { + PrintkError ("Bus error, DMA transfer failed"); + } + return; + } + } + + PrintkError ("DMA transfer timed out"); +} + + + + +/*-----------------------------------------------------------------------* + * * + * _ _ d m a s w _ b w r i t e * + * * + * Transfer data from RAM buffer to DiskOnChip's I/O reguster. * + * Example implementation For Texas Instruments OMAP1610 H2 board. * + * * + * Parameters: * + * off offset of DiskOnChip's I/O register from the base * + * of DiskOnChip window * + * vbuf virtual address of RAM buffer * + * bytes bytes to transfer * + * * + *-----------------------------------------------------------------------*/ +static +void __dmasw_bwrite ( int off, + void * vbuf, + unsigned int bytes ) +{ + register u32 tmp; + register int waiting; + + profiling[3]++; + + /* Channel Source/Destination Parameters. + * Specify 16-bit port width, EMIFF source, allow source packing, + * 4-words burst allowed for source, EMIFS destination. allow + * destination packing, 4-words burst allowed for destination. + */ + dma_regs->csdp = (BURST_4 << 14) | /* dest.: use 4-word burst */ + DCSDP_DST_PACK | /* pack dest. */ + (PORT_EMIFS << 9) | /* dest. is EMIFS (DiskOnChip) */ + (BURST_4 << 7) | /* source: use 4-word burt */ + DCSDP_SRC_PACK | /* pack source */ + (PORT_EMIFF << 2) | /* source is EMIFF (RAM) */ + DATA_TYPE_S16; /* 16-bit data path */ + + /* Channel Control Register. + * Specify no synchronization, no OMAP 3.0/3.1 compatibility, no + * frame synchronization, high priority, constant dest. address, + * post-increment source address. + */ + dma_regs->ccr = (AMODE_CONST << 14) | /* dest. (DiskOnChip): const addr. */ + (AMODE_POST_INC << 12) | /* source (RAM): post-increment */ + DCCR_N31COMP | /* no OMAP 3.1/3.0 compatibility */ + DCCR_PRIO; /* high priority */ + + /* Channel Frame Number Register. + * We assume that frame consists of single elemnt, and element consists + * of single 16-bit word. + */ + dma_regs->cfn = (bytes / sizeof(u16)); + + /* Channel Source Start Address Registers */ + if (tffs_dma_mode & 4) /* do DMA transfer directly from 'vbuf' */ + { + /* Write (if dirty) contents of 'vbuf' from CPU D-cache to RAM. + * Possible options: + * clean_dcache_range((unsigned long)vbuf, (unsigned long)(vbuf + bytes)); ARM/PPC + * consistent_sync(vbuf, bytes, PCI_DMA_TODEVICE); ARM/PPC + * dma_cache_wback((unsigned long)vbuf, (unsigned long)bytes); MIPS/PPC/SH/x86 + */ + clean_dcache_range ((unsigned long)vbuf, (unsigned long)(vbuf + bytes)); + + if (virt_addr_valid((unsigned long)vbuf)) /* 'vbuf' is in low memory */ + { + tmp = __pa (vbuf); + } + else /* 'vbuf' is in high memory */ + { + char * k_vbuf = (char *) page_address(vmalloc_to_page(vbuf)) + + ((unsigned long)vbuf & (PAGE_SIZE - 1)); + tmp = __pa (k_vbuf); + } + } + else /* use intermediate DMA buffer */ + { + /* move data from RAM buffer to the intermediate DMA buffer */ + memcpy (tffsInfo.dma_buf_vptr, vbuf, bytes); + + tmp = tffsInfo.dma_buf_paddr; + } + dma_regs->cssa_u = (tmp >> 16); + dma_regs->cssa_l = (tmp & 0xffff); + + /* Channel Destination Start Address Regist.This would be DiskOnChip's + * I/O register which is located at offset 'off' from the DiskOnChip's + * base address as specified by tffs_addr[0]). + */ + tmp = tffs_addr[0] + off; + dma_regs->cdsa_u = (tmp >> 16); + dma_regs->cdsa_l = (tmp & 0xffff); + + /* start DMA channel */ + dma_regs->ccr |= DCCR_EN; + + /* poll DMA channel's status register for end of DMA transfer */ + for (waiting = 100000; waiting > 0; waiting--) /* hope this is long enough ... */ + { + if (((tmp = dma_regs->ccr) & DCCR_EN) == 0) + { + if ((tmp = dma_regs->csr) & DCSR_ERROR) /* andrayk June 14 2006: DMA transfer failed, find way to let MTD know this */ + { + PrintkError ("Bus error, DMA transfer failed"); + } + return; + } + } + + PrintkError ("DMA transfer timed out"); +} + + + +#elif defined(CONFIG_ARCH_OMAP24XX) + +/*_____________________________________________________________________________ + | | + | | + | Texas Instruments OMAP-2420 (H4) board | + | | + |____________________________________________________________________________| +*/ + +# include +# include +/* # include */ /* conflicts with */ +# include +# include + +/* Routine blk_dma_inv_range_harvard() (arch/arm/mm/blockops.c) appears + * to be buggy: it seems to constantly shoot past the end of the address + * range [vbuf..vbuf+bytes] by 32 bytes. It also appears to write some + * bogus data into this RAM address range while invalidating it in D-cache. + */ +# define OMAP2420_DCACHE_BUG_WORKAROUND + + +# ifndef OMAP_DMA4_CCR_EN +# define OMAP_DMA4_CCR_EN (1 << 7) +# endif + +# define GPMC_CONFIG1_CS2 0xC0 /* phys. addr. 0x6800A0C0 */ +# define GPMC_CONFIG2_CS2 (GPMC_CONFIG1_CS2 + 0x4) /* phys. addr. 0x6800A0C4 */ +# define GPMC_CONFIG3_CS2 (GPMC_CONFIG1_CS2 + 0x8) /* phys. addr. 0x6800A0C8 */ +# define GPMC_CONFIG4_CS2 (GPMC_CONFIG1_CS2 + 0xC) /* phys. addr. 0x6800A0CC */ +# define GPMC_CONFIG5_CS2 (GPMC_CONFIG1_CS2 + 0x10) /* phys. addr. 0x6800A0D0 */ +# define GPMC_CONFIG6_CS2 (GPMC_CONFIG1_CS2 + 0x14) /* phys. addr. 0x6800A0D4 */ +# define GPMC_CONFIG7_CS2 (GPMC_CONFIG1_CS2 + 0x18) /* phys. addr. 0x6800A0D8 */ + +# ifndef OMAP2420_GPIO_SET_IRQENABLE1 +# define OMAP2420_GPIO_SET_IRQENABLE1 0x0064 +# endif +# ifndef OMAP2420_GPIO_CLEAR_IRQENABLE1 +# define OMAP2420_GPIO_CLEAR_IRQENABLE1 0x0060 +# endif +# ifndef OMAP2420_GPIO_IRQSTATUS1 +# define OMAP2420_GPIO_IRQSTATUS1 0x0018 +# endif +# ifndef OMAP2420_GPMC_BASE +# define OMAP2420_GPMC_BASE OMAP24XX_GPMC_BASE +# endif + +/* layout of DMA channel's registers */ +typedef struct { + volatile u32 ccr; /* Channel Control Register */ + volatile u32 clnk; /* Channel Link Control */ + volatile u32 cicr; /* Channel Interrupt Control Register */ + volatile u32 csr; /* Channel Status Register */ + volatile u32 csdp; /* Channel Source / Destination Parameters */ + volatile u32 cen; /* Channel Element Number */ + volatile u32 cfn; /* Channel Frame Number */ + volatile u32 cssa; /* Channel Source Start Address */ + volatile u32 cdsa; /* Channel Destination Start Address */ + volatile u32 csei; /* Channel Source Element Index */ + volatile u32 csfi; /* Channel Source Frame Index */ + volatile u32 cdei; /* Channel Destination Element Index */ + volatile u32 cdfi; /* Channel Destination Frame Index */ + volatile u32 csac; /* Channel Source Address Counter */ + volatile u32 cdac; /* Channel Destination Address Counter */ + volatile u32 ccen; /* Channel Current Element Number */ + volatile u32 ccfn; /* Channel Current Frame Number */ +} __dma_reg_t; + + +/* + * static routines for OMAP2420 + */ +static void tffs_dma_init (int resume); +static void tffs_dma_release (void); + + +/* + * static vars + */ +static __dma_reg_t * dma_regs_vptr = NULL; + + + +void omap24xx_enable_gpio_irq (int gpio_irq, int enable) +{ + register u32 gpio_line = gpio_irq - IH_GPIO_BASE; + register u32 bit = OMAP_GPIO_BIT(gpio_line); + register u32 base_reg = OMAP_GPIO_BASE_REG(gpio_line); + unsigned int val = 0; + + if (enable == TRUE) + { + writel (bit, (base_reg + OMAP2420_GPIO_SET_IRQENABLE1)); + __asm__ __volatile__("mcr p15, 0, %0, c7, c10, 4"::"r"(val)); /* memory barrier */ + + omap_set_gpio_edge_ctrl (gpio_line, OMAP_GPIO_LEVEL_LOW); + } + else + { + omap_set_gpio_edge_ctrl (gpio_line, 0); + + writel (bit, (base_reg + OMAP2420_GPIO_CLEAR_IRQENABLE1)); + __asm__ __volatile__("mcr p15, 0, %0, c7, c10, 4"::"r"(val)); /* memory barrier */ + + writel (bit, (base_reg + OMAP2420_GPIO_IRQSTATUS1)); + __asm__ __volatile__("mcr p15, 0, %0, c7, c10, 4"::"r"(val)); /* memory barrier */ + } +} + + + + +/*-----------------------------------------------------------------------* + * * + * t f f s a r c h _ i n i t * + * * + * This routine is called during module initialization time with 'resume'* + * argument set to FALSE, and from Power Manager's 'resume' routine with * + * 'resume' argument set to TRUE. If 'resume' is FALSE, this routine * + * allocates and initializes all required board resources; if 'resume' * + * is TRUE, this routine does minimal required re-initialization of * + * these resources after power suspend. For OMAP2420 (H4) board. * + * * + * Parameters: * + * suspend FALSE (module initialization) or TRUE (power resume) * + * * + * Returns: * + * always '1' (success) * + * * + *-----------------------------------------------------------------------*/ + +unsigned char tffsarch_init (int resume) +{ + register int tmp; + char * vp; + + if ((vp = (char *)ioremap_nocache(OMAP2420_GPMC_BASE, PAGE_SIZE)) == NULL) + { + PrintkError ("ioremap_nocache failed"); + } + else + { + /* Configure Chip Select that DiskOnChip is connected to. + * + * NOTE. Code below configures Chip Select to set duration of + * DiskOnChip access cycle to 65 nanosecond, which is + * appropriate for the case when DiskOnChip is connected to + * OMAP2420 board via M-Systems' adapters. If you solder + * DiskOnChip into your board, consider changing Chip Select + * settings to significantly shorten DiskOnChip acecss cycle. + * This should have significant positive efefct on + * DiskOnChip's 'read' performance. + */ + + tmp = (0 << 31) | /* synchronous wrapping burst not supported */ + (0 << 30) | /* single access */ + (0 << 29) | /* asynchronous read */ + (0 << 28) | /* single access */ + (0 << 27) | /* write asynchronous */ + (0 << 25) | /* start access time at first rising edge of GPMC.CLK */ + (0 << 23) | /* burst length 4 words */ + (0 << 22) | /* wait pin not monitored for read access */ + (0 << 21) | /* wait pin not monitored for write access */ + (0 << 18) | /* wait pin is monitored with valid data */ + (0 << 16) | /* wait input pin is WAIT0 */ + (1 << 12) | /* 16-bit device */ + (0 << 10) | /* NOR flash, pSRAM, or asynchronous device */ + (1 << 9) | /* address/data multiplexed attached device */ + (0 << 4) | /* x1 latencies */ + (3 << 0); /* GPMC.CLK = GPMC_FCLK/4 */ + writel (tmp /* 0x00001203 */, vp + GPMC_CONFIG1_CS2); + + tmp = (6 << 16) | /* nCS assertion time for write access */ + (6 << 8) | /* nCS assertion time for read access */ + (0 << 7) | /* nCS timing sygnal is not delayed */ + (0 << 0); /* nCS assertion time */ + writel (tmp /* 0x00060600 */, vp + GPMC_CONFIG2_CS2); + + tmp = (1 << 16) | /* nADV deassertion time for write access */ + (1 << 8) | /* nADV deassertion time for read access */ + (0 << 7) | /* nADV timing control sygnal is not delayed */ + (0 << 0); /* nADV assertion time */ + writel (tmp /* 0x00010100 */, vp + GPMC_CONFIG3_CS2); + + tmp = (5 << 24) | /* nWE deassertion time */ + (0 << 23) | /* nWE timing control sygnal is not delayed */ + (2 << 16) | /* nWE assertion time */ + (6 << 8) | /* nOE deassertion time */ + (0 << 7) | /* nOE timing control sygnal is not delayed */ + (2 << 0); /* nOE assertion time */ + writel (tmp /* 0x05020602 */, vp + GPMC_CONFIG4_CS2); + + tmp = (1 << 24) | /* delay between successive words in multiple access */ + (5 << 16) | /* delay between start-cycle and first data valid */ + (7 << 8) | /* total write cycle time in GPMC_FCLK cycles */ + (7 << 0); /* total read cycle time in GPMC_FCLK cycles */ + writel (tmp /* 0x01050707 */, vp + GPMC_CONFIG5_CS2); + + /* Map Chips Select CS2 at physical address 0x10000000 (as + * specified by macro TFFS_PHYS_ADDR). + */ + tmp = 0x00000F50; + writel (tmp, vp + GPMC_CONFIG7_CS2); + + iounmap (vp); + } + + if (tffs_irq >= 0) + { + register int gpio_line = (tffs_irq - IH_GPIO_BASE); + + if( omap_request_gpio(gpio_line) == 0 ) + { + register u8 x = readb (OMAP24XX_VA_SYSTEM_CONTROL_BASE + 0x10c); + + /* set GPIO function (mux mode 3), disable pullup/pulldown */ + x &= ~(MUXMODE_MASK); + x |= 3; + x &= ~(PULL_UD_ENABLE_MASK); + writeb (x, OMAP24XX_VA_SYSTEM_CONTROL_BASE + 0x10c); + + /* configure this GPIO line as input */ + omap_set_gpio_direction (gpio_line, TRUE); + + /* configure GPIO interrupt as level-low for this GPIO line */ +#if 0 + omap_set_gpio_edge_ctrl (gpio_line, /* OMAP_GPIO_LEVEL_LOW */ OMAP_GPIO_FALLING_EDGE); +#endif + } + else + { + PrintkWarning ("failed to get IRQ %d", tffs_irq); + tffs_irq = -1; + } + } + + /* if DMA is requested, configure it */ + if (tffs_dma_mode > 0) + { + tffs_dma_init (resume); + } + + return 1; +} + + + + +void TffsHWRelease(void) +{ + /* if DMA was actually used, release all DMA resources */ + if (tffs_dma_mode > 0) + { + tffs_dma_release (); + } + + /* if IRQ was actually used, release respective GPIO resources */ + if (tffs_irq >= 0) + { + register int gpio_line = (tffs_irq - IH_GPIO_BASE); + + omap_free_gpio (gpio_line); + } +} + + + + +/*-----------------------------------------------------------------------* + * * + * t f f s _ d m a _ i n i t * + * * + * This routine is called during module initialization time with 'resume'* + * argument set to FALSE, and from Power Manager's 'resume' routine with * + * 'resume' argument set to TRUE. If 'resume' is FALSE, this routine * + * allocates and initializes all required DMA resources; if 'resume' is * + * TRUE, this routine does minimal required re-initialization of DMA * + * channel after power suspend. For OMAP2420 (H4) board. * + * * + * Parameters: * + * suspend FALSE (module initialization) or TRUE (power resume) * + * * + *-----------------------------------------------------------------------*/ +static +void tffs_dma_init (int resume) +{ + register u32 tmp; + int rc; + + if (resume == FALSE) + { + /* We use single DMA channel for both 'read' and 'write' operations, + * so we allocate it here. We don't use DMA interrupts, so we won't + * need DMA callback. + */ + rc = omap_request_dma (0, + TFFS_DEVICE_NAME, + NULL, /* no callback when DMA completes */ + NULL, /* data to pass to DMA callback */ + &tffsInfo.channel); + + if ((rc != 0) || (tffsInfo.channel < 0) || + (tffsInfo.channel >= OMAP24XX_LOGICAL_DMA_CH_COUNT)) + { + /* failed to allocate DMA channel, won't use DMA */ + tffs_dma_mode = 0; + + PrintkError ("can't get DMA chan"); + return; + } + else + { + PrintkInfo ("use DMA channel %d", tffsInfo.channel); + + /* virt. address of DMA channel's register set */ + dma_regs_vptr = (__dma_reg_t *) + (OMAP_DMA4_BASE + (0x60 * tffsInfo.channel) + 0x80); + } + } + + /* Channel Control Register */ + tmp = (0 << 25) | /* buffering enabled */ + (0 << 24) | /* destination triggers DMA request */ + (1 << 23) | /* prefetch enabled */ + (0 << 21) | /* secure mode disabled */ + (0 << 19) | /* no synchronization */ + (1 << 18) | /* block synchronization */ + (0 << 17) | /* transaparent copy disabled */ + (0 << 16) | /* constant fill disabled */ + (1 << 14) | /* post-increment destination address */ + (0 << 12) | /* constant source address */ + (0 << 8) | /* ignore MSUSPEND */ + (0 << 7) | /* channel disabled (stopped) */ + (1 << 6) | /* high priority channel */ + (0 << 5) | /* no frame synchronization */ + (0 << 0); /* no synchronization (i.e. s/w DMA) */ + writel (tmp, &dma_regs_vptr->ccr); + + /* Channel Frame Number Register. + * We assume that frame consists of single element. + */ + writel (1, &dma_regs_vptr->cfn); + + /* Channel Interrupt Control Register. + * Disable all interrupts - we will be polling DMA controller. + */ + tmp = /* OMAP_DMA_DROP_IRQ | */ /* synchronization drop */ + /* OMAP_DMA_BLOCK_IRQ | */ /* end-of-block interrupt */ + /* (1 << 11) | */ /* misaligned address error */ + /* (1 << 8) | */ /* transaction error */ + 0; + writel (tmp, &dma_regs_vptr->cicr); + + /* Channel Status Register. + * Write all-ones to clear any pending interrupts. + */ + writel (~0, &dma_regs_vptr->csr); + + if (resume == FALSE) + { + tffsInfo.dma_buf_vptr = NULL; + tffsInfo.dma_buf_size = 0; + + if ((tffs_dma_mode >= 1) +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) || !defined(OMAP2420_DCACHE_BUG_WORKAROUND) + && (tffs_dma_mode <= 3) +#endif + ) + { + /* allocate intermediate DMA buffer (we assume one MMU page will be enough) */ + tffsInfo.dma_buf_size = PAGE_SIZE; + + tffsInfo.dma_buf_vptr = +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + consistent_alloc ((GFP_KERNEL | GFP_DMA), tffsInfo.dma_buf_size, + &tffsInfo.dma_buf_paddr); +#else + dma_alloc_coherent (NULL, tffsInfo.dma_buf_size, + &tffsInfo.dma_buf_paddr, (GFP_KERNEL | GFP_DMA)); +#endif + if (tffsInfo.dma_buf_vptr == NULL) + { + /* failed to allocate intermediate DMA buffer, won't use DMA */ + tffs_dma_mode = 0; + + omap_free_dma (tffsInfo.channel); + + tffsInfo.channel = -1; + tffsInfo.dma_buf_size = 0; + + dma_regs_vptr = NULL; + + PrintkError ("can't alloc DMA buffer, won't use DMA"); + } + } + } +} + + + + +/*-----------------------------------------------------------------------* + * * + * t f f s _ d m a _ r e l e a s e * + * * + * Release all previously allocated DMA resources (channel, intermediate * + * DMA buffer etc.). For OMAP2420 (H4) board. * + * * + *-----------------------------------------------------------------------*/ +static +void tffs_dma_release(void) +{ + /* if previously was allocated, release DMA channel */ + if (tffsInfo.channel >= 0) + { + omap_free_dma (tffsInfo.channel); + + tffsInfo.channel = -1; + dma_regs_vptr = NULL; + } + + /* if previously was allocated, release intermediate DMA buffer */ + if (tffsInfo.dma_buf_vptr != NULL) + { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + consistent_free (tffsInfo.dma_buf_vptr, PAGE_SIZE, tffsInfo.dma_buf_paddr); +#else + dma_free_coherent (NULL, PAGE_SIZE, tffsInfo.dma_buf_vptr, tffsInfo.dma_buf_paddr); +#endif + tffsInfo.dma_buf_vptr = NULL; + } +} + + + + +/*-----------------------------------------------------------------------* + * * + * _ _ d m a s w _ b r e a d * + * * + * Transfer data from DiskOnChip's I/O reguster to RAM buffer. * + * Example implementation For Texas Instruments OMAP2420 H4 board. * + * * + * Parameters: * + * off offset of DiskOnChip's I/O register from the base * + * of DiskOnChip window * + * vbuf virtual address of RAM buffer * + * bytes bytes to transfer * + * * + *-----------------------------------------------------------------------*/ +static +void __dmasw_bread ( int off, + void * vbuf, + unsigned int bytes ) +{ + register __dma_reg_t * regs = dma_regs_vptr; + register u32 tmp, tmp2; + register int waiting; + register int direct_dma; + + profiling[2]++; + + direct_dma = ((tffs_dma_mode & 4) ? TRUE : FALSE); + + /* Due to a bug in kernel routine blk_dma_inv_range_harvard() + * (arch/arm/mm/blockops.c), we allow direct DMA to destination + * buffer 'vbuf' only when it's aligned at CPU's cache line boundary. + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) && defined(OMAP2420_DCACHE_BUG_WORKAROUND) + if ((u32)vbuf & 31) + direct_dma = FALSE; +#endif + + /* Channel Source/Destination Parameters */ + tmp = (0 << 21) | /* little-endian source (DiskOnChip) */ + (1 << 20) | /* source endianism lock */ + (0 << 19) | /* little-endian destination (SDRAM) */ + (1 << 18) | /* destination endianism adapt */ + (1 << 16) | /* writes (to SDRAM) posted */ + (3 << 14) | /* 64-byte burst on destination (SDRAM) */ + (1 << 13) | /* destination (SDRAM) packed */ + (3 << 7) | /* 64-byte burst on source (DiskOnChip) */ + (1 << 6) | /* source (DiskOnChip) packed */ + (1 << 0) ; /* 16-bit data port width */ + writel (tmp, ®s->csdp); + + /* Channel Control Register */ + tmp2 = (0 << 25) | /* buffering enabled */ + (0 << 24) | /* destination triggers DMA request */ + (1 << 23) | /* prefetch enabled */ + (0 << 21) | /* secure mode disabled */ + (0 << 19) | /* no synchronization */ + (1 << 18) | /* block synchronization */ + (0 << 17) | /* transaparent copy disabled */ + (0 << 16) | /* constant fill disabled */ + (1 << 14) | /* post-increment destination address */ + (0 << 12) | /* constant source address */ + (0 << 8) | /* ignore MSUSPEND */ + (0 << 7) | /* channel disabled (stopped) */ + (1 << 6) | /* high priority channel */ + (0 << 5) | /* no frame synchronization */ + (0 << 0); /* no synchronization (i.e. s/w DMA) */ + writel (tmp2, ®s->ccr); + + /* Channel Element Number Register */ + writel ((bytes >> 1), ®s->cen); + + /* Channel Source Start Address Register. + * This would be DiskOnChip's I/O register which is located at offset + * 'off' from the DiskOnChip's base address as specified by tffs_addr[0]). + */ + writel ((tffs_addr[0] + off), ®s->cssa); + + /* Channel Destination Start Address Register. + * This would be physical address of intermediate DMA buffer (for + * DMA modes 1 and 3), or physical address of the destination buffer + * (for DMA modes 5 and 7). + */ + if (direct_dma == TRUE) /* do DMA transfer directly into 'vbuf' */ + { + if (virt_addr_valid((unsigned long)vbuf)) /* 'vbuf' is in low memory */ + { + tmp = __pa (vbuf); + } + else /* 'vbuf' is in high memory */ + { + char * k_vbuf = (char *) page_address(vmalloc_to_page(vbuf)) + + ((unsigned long)vbuf & (PAGE_SIZE - 1)); + if (k_vbuf == NULL) + { + PrintkError ("error, DMA requested on high memory page"); + return; + } + + tmp = __pa (k_vbuf); + } + + /* Write (if dirty) and purge contents of 'vbuf' from CPU cache(s) */ + /* Possible options: + * consistent_sync(vbuf, bytes, DMA_FROM_DEVICE); ARM/SH + * dma_cache_inv((unsigned long)vbuf, (unsigned long)bytes); MIPS/PPC/x86 + */ +#ifdef OMAP2420_DCACHE_BUG_WORKAROUND + /* Routine blk_dma_inv_range_harvard() (arch/arm/mm/blockops.c) appears + * to be buggy: it seems to constantly shoot past the end of the address + * range [vbuf..vbuf+bytes] by 32 bytes. It also appears to write some + * bogus data into this RAM address range while invalidating it in D-cache. + */ + consistent_sync (vbuf, bytes - 1, DMA_FROM_DEVICE); +#else + consistent_sync (vbuf, bytes, DMA_FROM_DEVICE); +#endif + + } + else /* transfer into intermediate DMA buffer */ + { + tmp = tffsInfo.dma_buf_paddr; + } + writel (tmp, ®s->cdsa); + + /* Channel Status Register. + * Write all-ones to clear any pending interrupts. + */ + writel (~0, ®s->csr); + + /* start DMA channel by setting ENABLED bit in Channel Control Register */ + writel ((tmp2 | OMAP_DMA4_CCR_EN), ®s->ccr); + + /* we don't want to see any of these DMA errors */ + tmp2 = (1 << 11) | /* misaligned error */ + (1 << 9) | /* secure transaction error */ + (1 << 8) | /* transaction error */ + (1 << 1); /* synchronization drop */ + + /* Wait for DMA transfer to finish (ENABLED bit in + * Channel Control Register changes to zero). + */ + for (waiting = 100000; waiting > 0; waiting--) /* hope this is long enough ... */ + { + if( readl(®s->ccr) & OMAP_DMA4_CCR_EN ) + continue; + + /* read Channel Status Register to find out status of DMA transfer */ + tmp = readl(®s->csr) & tmp2; + + /* write all-ones to clear any pending interrupts */ + writel (~0, ®s->csr); + + /* any errors ? */ + if (tmp == 0) + { + /* DMA transfer successfully completed, move data from intermediate + * DMA buffer to destination buffer (in case it was used). + */ + if (direct_dma == FALSE) + memcpy (vbuf, tffsInfo.dma_buf_vptr, bytes); + } + else /* andrayk June 13 2006: DMA transfer failed, find way to let MTD know this */ + { + PrintkError ("DMA transfer failed"); + } + return; + } + + PrintkError ("DMA transfer timed out"); +} + + + + +/*-----------------------------------------------------------------------* + * * + * _ _ d m a s w _ b w r i t e * + * * + * Transfer data from RAM buffer to DiskOnChip's I/O reguster. * + * Example implementation For Texas Instruments OMAP2420 H4 board. * + * * + * Parameters: * + * off offset of DiskOnChip's I/O register from the base * + * of DiskOnChip window * + * vbuf virtual address of RAM buffer * + * bytes bytes to transfer * + * * + *-----------------------------------------------------------------------*/ +static +void __dmasw_bwrite ( int off, + void * vbuf, + unsigned int bytes ) +{ + register __dma_reg_t * regs = dma_regs_vptr; + register u32 tmp, tmp2; + register int waiting; + + profiling[3]++; + + /* Channel Source/Destination Parameters */ + tmp = (0 << 21) | /* little-endian source (SDRAM) */ + (1 << 20) | /* source endianism locked */ + (0 << 19) | /* little-endian dest. (DiskOnChip) */ + (1 << 18) | /* destination endianism locked */ + (1 << 16) | /* writes (to DiskOnChip) posted */ + (0 << 14) | /* 64-byte burst on dest. (DiskOnChip) */ + (1 << 13) | /* destination (DiskOnChip) packed */ + (3 << 7) | /* 64-byte burst on source (SDRAM) */ + (1 << 6) | /* source (SDRAM) packed */ + (1 << 0) ; /* 16-bit data port width */ + writel (tmp, ®s->csdp); + + /* Channel Control Register */ + tmp2 = (0 << 25) | /* buffering enabled */ + (1 << 24) | /* source triggers DMA request */ + (1 << 23) | /* prefetch enabled */ + (0 << 21) | /* secure mode disabled */ + (0 << 19) | /* no synchronization */ + (1 << 18) | /* block synchronization */ + (0 << 17) | /* transaparent copy disabled */ + (0 << 16) | /* constant fill disabled */ + (0 << 14) | /* constant destination address */ + (1 << 12) | /* post-increment source address */ + (0 << 8) | /* ignore MSUSPEND */ + (0 << 7) | /* channel disabled (stopped) */ + (1 << 6) | /* high priority channel */ + (0 << 5) | /* no frame synchronization */ + (0 << 0); /* no synchronization (i.e. s/w DMA) */ + writel (tmp2, ®s->ccr); + + /* Channel Element Number Register */ + writel ((bytes >> 1), ®s->cen); + + /* Channel Source Start Address Register. + * This would be physical address of intermediate DMA buffer (for + * DMA modes 2 and 3), or physical address of the destination buffer + * (for DMA modes 6 and 7). + */ + if (tffs_dma_mode & 4) /* do DMA transfer directly from 'vbuf' */ + { + /* Write (if dirty) contents of 'vbuf' from CPU D-cache to RAM. + * Possible options: + * consistent_sync(vbuf, bytes, DMA_TO_DEVICE); ARM/SH + * dma_cache_wback((unsigned long)vbuf, (unsigned long)bytes); MIPS/PPC/x86 + */ + consistent_sync (vbuf, bytes, DMA_TO_DEVICE); + + if (virt_addr_valid((unsigned long)vbuf)) /* 'vbuf' is in low memory */ + { + tmp = __pa (vbuf); + } + else /* 'vbuf' is in high memory */ + { + char * k_vbuf = (char *) page_address(vmalloc_to_page(vbuf)) + + ((unsigned long)vbuf & (PAGE_SIZE - 1)); + if (k_vbuf == NULL) + { + PrintkError ("error, DMA requested on high memory page"); + return; + } + + tmp = __pa (k_vbuf); + } + } + else /* use intermediate DMA buffer */ + { + /* move data from RAM buffer to the intermediate DMA buffer */ + memcpy (tffsInfo.dma_buf_vptr, vbuf, bytes); + + tmp = tffsInfo.dma_buf_paddr; + } + writel (tmp, ®s->cssa); + + /* Channel Destination Start Address Register. + * This would be DiskOnChip's I/O register which is located at offset + * 'off' from the DiskOnChip's base address as specified by tffs_addr[0]). + */ + writel ((tffs_addr[0] + off), ®s->cdsa); + + /* Channel Status Register. + * Write all-ones to clear any pending interrupts. + */ + writel (~0, ®s->csr); + + /* start DMA channel by setting ENABLED bit in Channel Control Register */ + writel ((tmp2 | OMAP_DMA4_CCR_EN), ®s->ccr); + + /* we don't want to see any of these DMA errors */ + tmp2 = (1 << 11) | /* misaligned error */ + (1 << 9) | /* secure transaction error */ + (1 << 8) | /* transaction error */ + (1 << 1); /* synchronization drop */ + + /* Wait for DMA transfer to finish (ENABLED bit in + * Channel Control Register changes to zero). + */ + for (waiting = 100000; waiting > 0; waiting--) /* hope this is long enough ... */ + { + if( readl(®s->ccr) & OMAP_DMA4_CCR_EN ) + continue; + + /* read Channel Status Register to find out status of DMA transfer */ + tmp = readl(®s->csr) & tmp2; + + /* write all-ones to clear any pending interrupts */ + writel (~0, ®s->csr); + + /* any errors ? */ + if (tmp != 0) /* andrayk June 13 2006: DMA transfer failed, find way to let MTD know this */ + { + PrintkError ("DMA transfer failed"); + } + return; + } + + PrintkError ("DMA transfer timed out"); +} + + + + +#elif defined(CONFIG_OMAP_OSK) + +/*_____________________________________________________________________________ + | | + | | + | Texas Instruments OMAP OSK board | + | | + |____________________________________________________________________________| +*/ + + +unsigned char tffsarch_init (int resume) +{ + (*(short*)0xFFFEC808) = 0x00F5; + (*(short*)0xFFFEC808) = 0x00A0; + return 1; +} + +void TffsHWRelease(void) +{ } + +static void __dmasw_bread (int off, void * vbuf, unsigned int bytes) +{ } + +static void __dmasw_bwrite (int off, void * vbuf, unsigned int bytes) +{ } + + + + +#elif defined(CONFIG_ARCH_LUBBOCK) + +/*_____________________________________________________________________________ + | | + | | + | Intel PXA25x ("Lubbock") board | + | | + |____________________________________________________________________________| +*/ + +# define MSC2_CNTR_REG_ADDR 0x48000000 +# define MSC2_OFFSET 0x10 +# define MCS5_INIT_VAL 0xFFF80000 + +unsigned char tffsarch_init (int resume) +{ + volatile void *myMSC2ptr; + unsigned long msc2Val; + + myMSC2ptr = (volatile void *)ioremap_nocache(MSC2_CNTR_REG_ADDR, 0x1000); + /* MSC2 Static Memory Control Register - 16-bit mode for CS5 */ + msc2Val = readl( myMSC2ptr + MSC2_OFFSET ); + writel( ((msc2Val & 0x0000FFFF) | MCS5_INIT_VAL), myMSC2ptr + MSC2_OFFSET ); + /* *(myMCS5 + 4) = MCS5_INIT_VAL; */ + iounmap( (void *)myMSC2ptr); + + return 1; +} + +static void __dmasw_bread (int off, void * vbuf, unsigned int bytes) +{ } + +static void __dmasw_bwrite (int off, void * vbuf, unsigned int bytes) +{ } + + + +#elif defined(CONFIG_MACH_DATR) + +/*_____________________________________________________________________________ + | | + | | + | HaslerRail DATR board | + | | + |____________________________________________________________________________| +*/ + +#include +#include +#include + +/*-----------------------------------------------------------------------* + * * + * t f f s _ d m a _ i n t r * + * * + * Handle DMA interrupt on Intel PXA27x (Mainstone) board. * + * * + * Parameters: * + * dma interrupting DMA channel * + * dummy not used * + * regs not used * + * * + *-----------------------------------------------------------------------*/ + +static void tffs_dma_intr( + int dma, void *data +) { + register u_int tmp; + + /* check if interrupt came from our DMA channel */ + if (dma == tffsInfo.channel) + { + /* check if DMA transfer was successful */ + if ((tmp = DCSR(dma)) & DCSR_BUSERR) + { + /* andrayk Mar 24 2006: DMA transfer failed, find way to let MTD know this */ + PrintkError ("Bus error, DMA transfer failed"); + } + + /* clear DMA interrupt from this channel */ + DCSR(dma) = (tmp | (DCSR_BUSERR | DCSR_ENDINTR)); + } + else + { PrintkError ("received DMA interrupt on wrong channel"); } +} + +/*-----------------------------------------------------------------------* + * * + * t f f s _ d m a _ i n i t * + * * + * This routine is called during module initialization time with 'resume'* + * argument set to FALSE, and from Power Manager's 'resume' routine with * + * 'resume' argument set to TRUE. If 'resume' is FALSE, this routine * + * allocates and initializes all required DMA resources; if 'resume' is * + * TRUE, this routine does minimal required re-initialization of DMA * + * channel after power suspend. * + * * + * Parameters: * + * suspend FALSE (module initialization) or TRUE (power resume) * + * * + *-----------------------------------------------------------------------*/ + +#ifndef DALGN +#define DALGN __REG(0x400000a0) +#endif + +static void tffs_dma_init(int resume) { + if (!resume) { + /* We use single DMA channel for both 'read' and + * 'write' operations, so we allocate it here. + */ + tffsInfo.channel = pxa_request_dma(TFFS_DEVICE_NAME, DMA_PRIO_LOW, tffs_dma_intr, NULL); + if (tffsInfo.channel < 0) { + /* failed to allocate DMA channel, won't use DMA */ + tffs_dma_mode = 0; + + PrintkError ("can't get DMA chan"); + return; + } + PrintkInfo ("use DMA channel %d", tffsInfo.channel); + } + /* enable byte-aligned addresses */ + DALGN |= (1 << tffsInfo.channel); + /* clear any pending DMA errors/interrupts */ + DCSR(tffsInfo.channel) = (DCSR_NODESC | DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR); +} + +/*-----------------------------------------------------------------------* + * * + * t f f s _ d m a _ r e l e a s e * + * * + * Release all previously allocated DMA resources (channel, intermediate * + * DMA buffer etc.). For Intel PXA27x (Mainstone) board. * + * * + *-----------------------------------------------------------------------*/ + +static void tffs_dma_release(void) { + /* if previously was allocated, release DMA channel */ + if (tffsInfo.channel >= 0) { + pxa_free_dma(tffsInfo.channel); + tffsInfo.channel = -1; + } +} + +/*-----------------------------------------------------------------------* + * * + * t f f s _ d m a s w _ b r e a d * + * * + * Transfer data from DiskOnChip's I/O reguster to RAM buffer. * + * Example implementation For Intel PXA27x (Mainstone) board. * + * * + * Parameters: * + * off offset of DiskOnChip's I/O register from the base * + * of DiskOnChip window * + * vbuf virtual address of RAM buffer * + * bytes bytes to transfer * + * * + *-----------------------------------------------------------------------*/ + +void __dmasw_bread(int off, void *vbuf, unsigned int bytes) { + u_int tmp; + int waiting; +// unsigned char *p = vbuf; +// int i; + + /* write (if dirty) and purge contents of 'vbuf' from CPU cache(s) */ + /* D-cache only */ + dma_cache_maint(vbuf, bytes, DMA_FROM_DEVICE); + /* set target physical address for DMA transfer */ + DTADR(tffsInfo.channel) = __pa(vbuf); + /* Set source physical address for DMA transfer (this would be DiskOnChip's + * I/O register which is located at offset 'off' from the DiskOnChip's + * base address as specified by fl_win[0]). + */ + DSADR(tffsInfo.channel) = tffs_addr[0] + off; + /* specify parameters of DMA transfer */ + tmp = DCMD_INCTRGADDR | /* increment target address */ + DCMD_WIDTH2 | /* 16-bit data path */ + DCMD_BURST32 | /* 32-bytes burst */ + /* DCMD_ENDIRQEN | */ /* don't generate interrupt at the end of transfer */ + bytes; + DCMD(tffsInfo.channel) = tmp; + /* clear all status bits, and start DMA transfer */ + DCSR(tffsInfo.channel) = (DCSR_RUN | DCSR_NODESC | DCSR_ENDINTR | DCSR_STOPSTATE | DCSR_BUSERR); + + /* poll DMA channel's status register for end of DMA transfer */ + for (waiting = 100000; waiting > 0; waiting--) /* hope this is long enough ... */ + { + if ((tmp = DCSR(tffsInfo.channel)) & (DCSR_STOPSTATE | DCSR_BUSERR)) + { + if ((tmp & DCSR_BUSERR) == 0) + { + /* DMA transfer completed */ + } + else + { + PrintkError ("Bus error, DMA transfer failed"); + /* andrayk Mar 24 2006: DMA transfer failed, find way to let MTD know this */ + } + return; + } + } + PrintkError ("DMA transfer timed out"); +} + +/*-----------------------------------------------------------------------* + * * + * t f f s _ d m a s w _ b w r i t e * + * * + * Transfer data from RAM buffer to DiskOnChip's I/O reguster. * + * Example implementation for Intel PXA27x (Mainstone) board. * + * * + * Parameters: * + * off offset of DiskOnChip's I/O register from the base * + * of DiskOnChip window * + * vbuf virtual address of RAM buffer * + * bytes bytes to transfer * + * * + *-----------------------------------------------------------------------*/ + +void __dmasw_bwrite ( int off, + void * vbuf, + unsigned int bytes ) +{ + u_int tmp; + int waiting; + + /* write (if dirty) contents of 'vbuf' from CPU D-cache to RAM */ + dma_cache_maint(vbuf, bytes, DMA_TO_DEVICE); + /* set source physical address for DMA transfer */ + DSADR(tffsInfo.channel) = __pa(vbuf); + /* Set target physical address for DMA transfer (this would be DiskOnChip's + * I/O register which is located at offset 'off' from the DiskOnChip's + * base address as specified by tffs_addr[0]). + */ + DTADR(tffsInfo.channel) = tffs_addr[0] + off; + /* specify parameters of DMA transfer */ + tmp = DCMD_INCSRCADDR | /* increment source address */ + DCMD_WIDTH2 | /* 16-bit data path */ + DCMD_BURST32 | /* 32-bytes burst */ + /* DCMD_ENDIRQEN | */ /* don't generate interrupt at the end of transfer */ + bytes; + DCMD(tffsInfo.channel) = tmp; + /* clear all status bits, and start DMA transfer */ + DCSR(tffsInfo.channel) = (DCSR_RUN | DCSR_NODESC | DCSR_ENDINTR | DCSR_STOPSTATE | DCSR_BUSERR); + + /* poll DMA channel's status register for end of DMA transfer */ + for (waiting = 100000; waiting > 0; waiting--) /* hope this is long enough ... */ + { + if ((tmp = DCSR(tffsInfo.channel)) & (DCSR_STOPSTATE | DCSR_BUSERR)) + { + if (tmp & DCSR_BUSERR) + { + PrintkError ("Bus error, DMA transfer failed"); + /* andrayk Mar 24 2006: DMA transfer failed, find way to let MTD know this */ + } + return; + } + } + PrintkError ("DMA transfer timed out"); +} + +unsigned char tffsarch_init(int resume) { + /* configure /CS2 as 16-bit VLIO */ + MSC1 = (MSC1 & 0xffff0000) | 0x023C; + /* configure GPIO11 as IRQ */ +#if 1 + if (gpio_request(11, "door") || gpio_direction_input(11)) { + printk("failed to setup GPIO as TFFS irq\n"); + } + set_irq_type(IRQ_GPIO(11), IRQF_TRIGGER_FALLING); +#else + pxa_gpio_mode(11 | GPIO_IN); + set_irq_type(IRQ_GPIO(11), IRQT_FALLING); +#endif + if (tffs_dma_mode > 0) { + tffs_dma_init(resume); + } + return 1; +} + +void TffsHWRelease(void) +{ + /* if DMA was actually used, release all DMA resources */ + if (tffs_dma_mode > 0) { + tffs_dma_release (); + } +} + +#else /* ARCH */ + +/*_____________________________________________________________________________ + | | + | | + | All other boards | + | | + |____________________________________________________________________________| +*/ + +unsigned char tffsarch_init (int resume) +{ + return 1; +} + +void TffsHWRelease(void) +{ } + +static void __dmasw_bread (int off, void * vbuf, unsigned int bytes) +{ } + +static void __dmasw_bwrite (int off, void * vbuf, unsigned int bytes) +{ } + +#endif /* ARCH */ + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/tffsarch.h linux-2.6.30.4/drivers/block/tffs/tffsarch.h --- linux-2.6.30.4-orig/drivers/block/tffs/tffsarch.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/tffsarch.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,197 @@ +/****************************************************************************** + * * + * Project: DOC Driver for Linux 2.6 Block device driver for mDOC H3 family * + * of devices under Linux kernel 2.6. * + * * + * Version: 1.0 * + * Email questions to: oemsupport@sandisk.com * + * Copyright (C) SanDisk IL Ltd. 1995 - 2007 * + * SanDisk IL Ltd., 7 Atir Yeda Street, Kfar Saba 44425, Israel * + * * + ****************************************************************************** + * * + * 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 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, which is set forth in the readme.txt file. * + * 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., 51 * + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + * * + * This License does not grant you any right to use the trademarks, service * + * marks or logos of SanDisk IL Ltd. or SanDisk Corporation. * + * Subject to the foregoing, SanDisk IL Ltd., for itself and on behalf of its * + * licensors, hereby reserves all intellectual property rights in the program,* + * except for the rights expressly granted in this License. * + * * + ******************************************************************************/ + +/* + * $Log$ + */ + + +#ifndef TFFSARCH_H +#define TFFSARCH_H + + + +/* + * includes + */ + +#include +#include + + +/* + * Physical address of DiskOnChip device. + * + * M-Systems provides default values for variety of popular boards (see also + * documentation for respective DiskOnChip adaptors for these boards). If you + * are using different board, you'll need to define TFFS_PHYS_ADDR as + * appropriate for your system. + */ +#if defined(CONFIG_ARCH_MAINSTONE) || defined(CONFIG_MACH_MAINSTONE) +# define TFFS_PHYS_ADDR 0x14000000 /* chip select CS5 on Intel PXA27x Mainstone */ +#elif defined(CONFIG_ARCH_LUBBOCK) +# define TFFS_PHYS_ADDR 0x14000000 +#elif defined(CONFIG_ARCH_OMAP24XX) +# define TFFS_PHYS_ADDR 0x10000000 /* chip select CS2 on Texas Instruments OMAP2420 */ +#elif defined(CONFIG_OMAP_H2) || defined(CONFIG_MACH_OMAP_H2) +# define TFFS_PHYS_ADDR 0x8000000 +#elif defined(CONFIG_OMAP_OSK) +# define TFFS_PHYS_ADDR 0x6000000 +#elif defined(CONFIG_M386) || defined(CONFIG_M486) || defined(CONFIG_M586) || defined(CONFIG_M586TSC) || defined(CONFIG_M586MMX) || defined(CONFIG_M686) || defined(CONFIG_MPENTIUMIII) || defined(CONFIG_MPENTIUM4) +# define TFFS_PHYS_ADDR 0xd0000 +#elif defined(CONFIG_MACH_DATR) +# define TFFS_PHYS_ADDR 0x08000000 +#else +# define TFFS_PHYS_ADDR 0 +#endif +extern unsigned long tffs_addr []; + + +/* + * Board's IRQ line that DiskOnChip's IREQ is connected to. + * + * M-Systems provides default values for variety of popular boards (see also + * documentation for respective DiskOnChip adaptors for these boards). If you + * are using different board, you'll need to define TFFS_IRQ as + * appropriate for your system, or set it to (-1) if you don't want to use + * DiskOnChip IREQ. + */ +#if defined(CONFIG_ARCH_MAINSTONE) || defined(CONFIG_MACH_MAINSTONE) +# define TFFS_IRQ MAINSTONE_IRQ(7) /* Intel PXA27x ("Mainstone") */ +#elif defined(CONFIG_ARCH_LUBBOCK) +# define TFFS_IRQ (-1) +#elif defined(CONFIG_ARCH_OMAP24XX) +# define TFFS_IRQ (-1) /* OMAP_GPIO_IRQ_NO(94), if using GPIO line 94 */ +#elif defined(CONFIG_OMAP_H2) || defined(CONFIG_MACH_OMAP_H2) /* Texas Instruments OMAP1610 SDP ("H2") */ +# define TFFS_IRQ (-1) /* was INT_GPIO_9, or numerically 169 */ +#elif defined(CONFIG_OMAP_OSK) +# define TFFS_IRQ (-1) +#elif defined(CONFIG_M386) || defined(CONFIG_M486) || defined(CONFIG_M586) || defined(CONFIG_M586TSC) || defined(CONFIG_M586MMX) || defined(CONFIG_M686) || defined(CONFIG_MPENTIUMIII) || defined(CONFIG_MPENTIUM4) +# define TFFS_IRQ (-1) +#elif defined(CONFIG_MACH_DATR) +# define TFFS_IRQ gpio_to_irq(11) +#else +# define TFFS_IRQ (-1) +#endif + + +/* # define FL_XSCALE_BOOT_MODE */ + + +/* DiskOnChip driver uses 'flRead512Bytes' macro to transfer 512-bytes of + * data from DiskOnChip to destination RAM buffer. We check if s/w DMA + * is enabled for 'read' operations, and if buffer is properly aligned. + * If they are, we use s/w DMA to transfer data; otherwise we use TrueFFS' + * internal C loops to transfer data in 16-bit short words. + */ + extern int tffs_dma_mode; + + extern void tffs_readw (unsigned long io_vaddr, short *vbuf, int words); + extern void tffs_writew (unsigned long io_vaddr, short *vbuf, int words); + extern void tffs_dmasw (char *win, int off, void *vbuf, unsigned int bytes, int read); + +#if defined(CONFIG_ARCH_MAINSTONE) || defined(CONFIG_MACH_MAINSTONE) || defined(CONFIG_OMAP_H2) || defined(CONFIG_MACH_OMAP_H2) || defined(CONFIG_ARCH_OMAP24XX) + +# define flReadEvenNumberOfBytes(flash,off,vbuf,bytes) \ + ( \ + ((tffs_dma_mode & 1) && ((bytes) >= 512) && ((((long)(vbuf)) & (sizeof(long) - 1)) == 0)) \ + ? \ + tffs_dmasw(((char*)((flash)->win)),(off),(vbuf),(bytes),1) \ + : \ + tffs_readw(((unsigned long)(((char *)((flash)->win)) + (off))),((short*)(vbuf)),((bytes) / sizeof(short))) \ + ) + +# define flWriteEvenNumberOfBytes(flash,off,vbuf,bytes) \ + ( \ + ((tffs_dma_mode & 2) && ((bytes) >= 512) && ((((long)(vbuf)) & (sizeof(long) - 1)) == 0)) \ + ? \ + tffs_dmasw(((char*)((flash)->win)),(off),(vbuf),(bytes),0) \ + : \ + tffs_writew(((unsigned long)((char*)((flash)->win) + (off))),((short*)(vbuf)),((bytes) / sizeof(short))) \ + ) + +#elif defined(CONFIG_MACH_DATR) + +# define flReadEvenNumberOfBytes(flash,off,vbuf,bytes) \ + ( \ + ((tffs_dma_mode & 1) && virt_addr_valid(vbuf)) \ + ? \ + tffs_dmasw(((char*)((flash)->win)),(off),(vbuf),(bytes),1) \ + : \ + tffs_readw(((unsigned long)(((char *)((flash)->win)) + (off))),((short*)(vbuf)),((bytes) / sizeof(short))) \ + ) + +# define flWriteEvenNumberOfBytes(flash,off,vbuf,bytes) \ + ( \ + ((tffs_dma_mode & 2) && virt_addr_valid(vbuf)) \ + ? \ + tffs_dmasw(((char*)((flash)->win)),(off),(vbuf),(bytes),0) \ + : \ + tffs_writew(((unsigned long)((char*)((flash)->win) + (off))),((short*)(vbuf)),((bytes) / sizeof(short))) \ + ) + +#else /* not Mainstone/OMAP1610/OMAP2420 */ + +# define flReadEvenNumberOfBytes(flash,off,vbuf,bytes) \ + tffs_readw(((unsigned long)((char*)((flash)->win) + (off))),((short*)(vbuf)),((bytes) / sizeof(short))) + +# define flWriteEvenNumberOfBytes(flash,off,vbuf,bytes) \ + tffs_writew(((unsigned long)((char*)((flash)->win) + (off))),((short*)(vbuf)),((bytes) / sizeof(short))) + +#endif /* ARCH */ + + + +/* DiskOnChip driver uses DOCHBLK_READ and DOCHBLK_WRITE macros to transfer + * data from and from (respectively) DiskOnChip H3 devices. + */ +# define DOCHBLK_READ(reg_base,vbuf,sectors) dochblk_read((vbuf),(sectors)) +# define DOCHBLK_WRITE(reg_base,vbuf,sectors) dochblk_write((vbuf),(sectors)) + +# if 0 /* andrayk June 23 2006: added for H3 burst */ +# define DOCHREAD_BURST(reg_base,offset,vbuf,sectors) dochblk_read((vbuf),(sectors)) +# define DOCHWRITE_BURST(reg_base,offset,vbuf,sectors) dochblk_write((vbuf),(sectors)) +#endif + +extern int dochblk_read (void *vbuf, unsigned int sectors); +extern int dochblk_write (void *vbuf, unsigned int sectors); + + +extern unsigned char tffsarch_init (int resume_flag); +extern void TffsHWRelease (void); + + +#ifdef CONFIG_ARCH_OMAP24XX + extern void omap24xx_enable_gpio_irq (int gpio_irq, int enable); +#endif + + +#endif /* TFFSARCH_H */ diff -urN linux-2.6.30.4-orig/drivers/block/tffs/tffsdrv26.c linux-2.6.30.4/drivers/block/tffs/tffsdrv26.c --- linux-2.6.30.4-orig/drivers/block/tffs/tffsdrv26.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/tffsdrv26.c 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,1800 @@ +/****************************************************************************** + * * + * Project: DOC Driver for Linux 2.6 Block device driver for mDOC H3 family * + * of devices under Linux kernel 2.6. * + * * + * Version: 1.0 * + * Email questions to: oemsupport@sandisk.com * + * Copyright (C) SanDisk IL Ltd. 1995 - 2007 * + * SanDisk IL Ltd., 7 Atir Yeda Street, Kfar Saba 44425, Israel * + * * + ****************************************************************************** + * * + * 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 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, which is set forth in the readme.txt file. * + * 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., 51 * + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + * * + * This License does not grant you any right to use the trademarks, service * + * marks or logos of SanDisk IL Ltd. or SanDisk Corporation. * + * Subject to the foregoing, SanDisk IL Ltd., for itself and on behalf of its * + * licensors, hereby reserves all intellectual property rights in the program,* + * except for the rights expressly granted in this License. * + * * + ******************************************************************************/ + +/* + * $Log$ + */ + + +#include "tffsdrv.h" + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) + +#include "tffs2lnx.h" +#include "flbase.h" +#include + + + +MODULE_AUTHOR("M-Systems"); +MODULE_DESCRIPTION("TrueFFS driver"); +MODULE_LICENSE("GPL"); +MODULE_SUPPORTED_DEVICE(TFFS_SUPPORTED_DEVICE); + + + +/* + * module parameters + */ + +/* major device # to use */ +int tffs_major = 100; +module_param(tffs_major, int, S_IRUGO); +MODULE_PARM_DESC(tffs_major, "major device number, zero to use dynamic."); + +/* priority of driver's I/O threads */ +static int tffs_prio = 0; /* max -20, min 19 */ +module_param(tffs_prio, int, (S_IRUGO | S_IWUSR)); +MODULE_PARM_DESC(tffs_prio,"priority of DiskOnChip I/O thread."); + +/* interrupt line that DiskOnChip's IREQ is connected to */ +int tffs_irq = TFFS_IRQ; +module_param(tffs_irq, int, S_IRUGO); +MODULE_PARM_DESC(tffs_irq, "Interrupt line DiskOnChip's IREQ is connected to."); + +/* DMA mode. Allowed modes are: + * 0 (don't use DMA) + * 1 (use s/w DMA in read operations only; uses intermediate DMA buffer) + * 2 (use s/w DMA in write operations only; uses intermediate DMA buffer) + * 3 (combined 1 and 2) + * 5 (use s/w DMA for direct transfers from user source buffers) + * 6 (use s/w DMA for direct transfers to user dest. buffers) + * 7 (combined 5 and 6) + * Default is don't use DMA. + */ +int tffs_dma_mode = 7; +module_param(tffs_dma_mode, int, S_IRUGO); +MODULE_PARM_DESC(tffs_dma_mode, "DMA mode (0, 1, 2, 3, 5, 6 or 7)."); + +/* Automatic Deep PowerDown mode. Allowed modes are 0 (default; disabled), + * or 1 (enabled). When enabled, Automatic Deep PowerDown mode will cause + * DiskOnChip driver to power down DiskOnChip after completion of every + * read/write operation, and power it up again before starting the next one. + */ +int tffs_auto_dpd = FL_OFF; +module_param(tffs_auto_dpd, int, S_IRUGO); +MODULE_PARM_DESC(tffs_auto_dpd, "Powerdown DiskOnChip after every operation (1), or don't (0)."); + +/* Upon completion of every read/write access, DiskOnChip H3 devices + * immediately switch from the normal mode into the idle mode, and stay + * in the idle mode for 'DOCH_DPD_DEFAULT_DPD_TIMEOUT' milliseconds before + * switching into deep-power-down mode. + */ +int tffs_dpd_timeout = 1; +module_param(tffs_dpd_timeout, int, S_IRUGO); +MODULE_PARM_DESC(tffs_dpd_timeout, "Time (in milliseconds) before DiskOnChip automatically powers itself down."); + +/* Read data from DiskOnChip into scatter/gather buffer, then scatter it to + * destination buffers. Allowed values are TRUE (scatter data) or FALSE (don't). + */ +int tffs_sg_read = TRUE; +module_param(tffs_sg_read, int, S_IRUGO); +MODULE_PARM_DESC(tffs_sg_read, "Use scatter/gather during read operations."); + +/* Gather data from source buffers into scatter/gather buffer before writing + * it to DiskOnChip. Allowed values are TRUE (gather data) or FALSE (don't). + */ +int tffs_sg_write = TRUE; +module_param(tffs_sg_write, int, S_IRUGO); +MODULE_PARM_DESC(tffs_sg_write, "Use scatter/gather during write operations."); + +/* size of scatter/gather buffer in bytes; must be multiple of PAGE_SIZE */ +int tffs_sg_bufsize = (16 * PAGE_SIZE); +module_param(tffs_sg_bufsize, int, S_IRUGO); +MODULE_PARM_DESC(tffs_sg_bufsize, "Size of scatter/gather buffer, in bytes."); + + + + +/* + * macros + */ +#ifndef _MIN +# define _MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + + + + +/* + * types + */ +struct scatter_t /* scatter buffer for READ requests */ +{ + char * buf; /* starting address */ + char * pcurrent; + unsigned int size; /* size of buffer in bytes */ + unsigned int remaining_bytes; + sector_t start_sector; /* starting disk sector # */ + unsigned int sectors; /* remaining sectors in this request */ +}; + +struct gather_t /* gather buffer for WRITE requests */ +{ + char * buf; /* starting address */ + char * free; /* free part fo the buffer */ + unsigned int size; /* size of buffer in bytes */ + unsigned int free_bytes; /* remaining free space in bytes */ + sector_t start_sector; /* starting disk sector # */ +}; + + + + +/* + * global vars + */ +int write_requests = 0; + + + + +/* + * static routines + */ +static int /* __init */ __tffs_module_init (void); +static void /* __init */ init_socket (SocketInfo *psoc); +static void /* __init */ init_disk (DeviceInfo *pdisk); +static void /* __exit */ release_socket (SocketInfo *psoc); +static void /* __exit */ release_disk (DeviceInfo * pdisk); +static void cleanup (int STEP); + +static void disk_request_queue_handler (struct request_queue *q); +static int socket_io_thread (void *arg); +static int requests_to_do (SocketInfo *psoc); +static void do_requests_list (SocketInfo *psoc); +static int do_write_request (struct request *r); +static int do_read_request (struct request *r); +static int rw_bio_no_sg (struct bio *bio, DeviceInfo *pdisk, int rw); +static int write_bio (struct bio *bio, struct gather_t *gather, DeviceInfo *pdisk); +static int read_bio (struct bio *bio, struct scatter_t *scatter, DeviceInfo *pdisk); + +static int disk_open (struct block_device *bdev, fmode_t mode); +static int disk_close (struct gendisk* gd, fmode_t mode); +static int disk_ioctl (struct block_device *bdev, fmode_t mode, unsigned cmd, unsigned long arg); + +static irqreturn_t interrupt_handler (int irq, void *psoc); + +#ifdef CONFIG_PROC_FS + static int /* __init */ procfs_register (DeviceInfo *pdisk); + static int /* __exit */ procfs_unregister (DeviceInfo *pdisk); + static int procfs_write (struct file* file, const char* buffer, unsigned long count, void* data); + static int procfs_read (char* buffer, char** start, off_t offset, int length, int* eof, void* data); +#endif + + + + +/* + * static vars + */ +static struct semaphore open_close_mutex; /* used to serialize disk open/close calls */ + +static char tffs_str[] = TFFS_DEVICE_NAME; + +static struct block_device_operations tffs_bdev_ops = +{ + .open = disk_open, + .release = disk_close, + .ioctl = disk_ioctl, + .owner = THIS_MODULE +}; + +/* for tracking enabled/disabled state of IRQ that DiskOnChip is connected to */ +static spinlock_t __irq_lock = SPIN_LOCK_UNLOCKED; +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_MAINSTONE) || defined(CONFIG_MACH_MAINSTONE) + static int __irq_enabled = TRUE; +#else + static int __irq_enabled = FALSE; +#endif + + + + +/******************************************************************************* + * * + * t f f s _ m o d u l e _ i n i t * + * * + * Module initialization routine. * + * * + * Parameters: none * + * * + * Returns: zero if success, otherwise standard negative error code * + * * + *******************************************************************************/ + +int /* __init */ tffs_module_init (void) +{ +# ifdef TRACE32 /* needed for section relocation in TRACE32 */ + extern int trace32_data; + extern int trace32_bss; + extern const int trace32_rodata; + printk ("\n\nTRACE32 section relocation: .data=0x%lx .bss=0x%lx .rodata=0x%lx\n\n", + (long)(&trace32_data), (long)(&trace32_bss), (long)(&trace32_rodata)); +# endif + + return __tffs_module_init(); +} + +module_init(tffs_module_init); + + + + +/******************************************************************************* + * * + * t f f s _ m o d u l e _ e x i t * + * * + * Module cleanup and routine; called when module is unloaded. * + * * + * Parameters: none * + * * + *******************************************************************************/ + +void /* __exit */ tffs_module_exit (void) +{ + cleanup (100); +} + +module_exit(tffs_module_exit); + + + + +/******************************************************************************* + * * + * _ _ t f f s _ m o d u l e _ i n i t * + * * + * Initialize DiskOnChip driver. * + * * + * Parameters: none * + * * + * Returns: zero if success, otherwise standard negative error code * + * * + *******************************************************************************/ +static +int /* __init */ __tffs_module_init (void) +{ + int STEP, iSoc, tmp; + + STEP = 0; + + PrintkInfo ("mDOC driver %s.%d", TrueFFSVersion, TFFS_DRV_VER); + + memset (tffsInfo.sockets, 0, sizeof(tffsInfo.sockets)); + + for (iSoc = 0; iSoc < FL_SOCKETS; iSoc++) + { + init_completion (&tffsInfo.sockets[iSoc].wait_for_irq); /* sema_init (&tffsInfo.sockets[iSoc].sleep_sem, 0); */ + + init_waitqueue_head (&tffsInfo.sockets[iSoc].waitQueueHead); + } + + STEP++; /* 1 */ + + /* if requested, install handler for DiskOnChip interrupts */ + if (tffs_irq >= 0) + { + if( request_irq(tffs_irq, interrupt_handler, 0 /* SA_INTERRUPT */, + tffs_str, &tffsInfo.sockets[0]) == 0 ) + { + tffs_irq_disable (TRUE); + + PrintkInfo ("use IRQ %d", tffs_irq); + } + else /* can't install interrupt handler, won't use IRQ */ + { + PrintkWarning ("failed to get IRQ %d", tffs_irq); + tffs_irq = -1; + } + } + else { PrintkInfo ("will not use IRQ"); } + + STEP++; /* 2 */ + + /* Find all DiskOnChip sockets, find out how many disks are on + * each socket, and abs.mount each disk. + */ + if( TffsInit() <= 0 ) + { + PrintkError ("No DiskOnChips found"); + return -ENODEV; + } + + STEP++; /* 3 */ + + if (tffs_irq >= 0) + { + /* enable interrupt generation in DiskOnChip */ + TffsEnableIRQ (&tffsInfo.sockets[0]); + } + + STEP++; /* 4 */ + + /* Register our major device # (or accept dynamically allocated + * major #). + */ + if ((tmp = register_blkdev(tffs_major, tffs_str)) < 0) + { + PrintkError ("Can't get major %d", tffs_major); + cleanup (STEP); + return -EBUSY; + } + if (tffs_major == 0) /* we asked for dynamic major #, and we got it */ + tffs_major = tmp; + PrintkInfo ("use major device number %d", tffs_major); + + STEP++; /* 5 */ + +#ifdef CONFIG_PROC_FS + if ((tffsInfo.pProcDir = proc_mkdir(tffs_str, NULL)) == NULL) + { PrintkWarning ("Can't create /proc/%s", tffs_str); } +#endif + + STEP++; /* 6 */ + + /* initialize Open/Close mutex in "available" state */ + sema_init (&open_close_mutex, 1); + + /* init sockets */ + for (iSoc = 0; iSoc < FL_SOCKETS; iSoc++) + init_socket (&tffsInfo.sockets[iSoc]); + + STEP++; /* 7 */ + +#ifdef CONFIG_PM + tffs_pm_init (); /* register with Power Manager */ +#endif + + STEP++; /* 8 */ + + return 0; +} + + + + +/******************************************************************************* + * * + * i n i t _ s o c k e t * + * * + * Initialize socket's I/O thread and all socket's disks. * + * * + * Parameters: * + * psoc pointer to socket being initialized * + * * + *******************************************************************************/ +static +void /* __init */ init_socket ( SocketInfo * psoc ) +{ + int iDisk; + + if (psoc->fFound == 0) + return; + + init_completion (&psoc->wait_for_io_thread); /* sema_init (&psoc->threadSemaphore, 0); */ + + /* Tell I/O thread to wake us up once it gets up and running */ + psoc->io_thread_state = 2; + + /* start socket's I/O thread */ + kernel_thread (socket_io_thread, (void *)psoc, 0); + + /* wait until socket's I/O thread is up and running */ + wait_for_completion (&psoc->wait_for_io_thread); /* down_interruptible (&psoc->threadSemaphore); */ + + /* socket's I/O thread has been started, and is currently waiting for + * I/O requests to be posted to psoc->waitQueueHead. + */ + for (iDisk = 0; iDisk < psoc->wDevices; iDisk++) + init_disk (&psoc->pDevices[iDisk]); +} + + + + +/******************************************************************************* + * * + * i n i t _ d i s k * + * * + * Initialize individual disk. s). * + * * + * Parameters: * + * pdisk pointer to disk * + * * + *******************************************************************************/ +static +void /* __init */ init_disk ( DeviceInfo * pdisk ) +{ + struct gendisk * gd; + int max_partitions; + + /* nobody has opened this disk yet */ + pdisk->in_use = 0; + +#ifdef TFFS_STATISTIC + memset (&pdisk->stat, 0, sizeof(pdisk->stat)); +#endif + +#ifdef CONFIG_PROC_FS + procfs_register (pdisk); +#endif + + /* allocate request queue for this disk */ + spin_lock_init (&pdisk->rq_lock); + + pdisk->rq = blk_init_queue (disk_request_queue_handler, &pdisk->rq_lock); + if (pdisk->rq == NULL) + { + PrintkError ("blk_init_queue() failed for disk 0x%x", pdisk->bHandle); + return; + } + else + pdisk->rq->queuedata = pdisk; + + /* Maximum number of file system partitions that we allow + * on the disk (this doesn't include "raw" disk). + */ + max_partitions = ((1 << DEV2PART_SHIFT) - 1); + + /* allocate struct gendisk for this disk */ + if ((gd = alloc_disk(max_partitions)) == NULL) + { + /* return previously allocated request queue to the system */ + blk_cleanup_queue (pdisk->rq); + pdisk->rq = NULL; + + PrintkError ("alloc_disk() failed for disk 0x%x", pdisk->bHandle); + return; + } + else + pdisk->gd = gd; + + gd->major = tffs_major; + gd->first_minor = (pdisk->diskNo * (max_partitions + 1/*"raw" disk entry*/)); + gd->fops = &tffs_bdev_ops; + gd->queue = pdisk->rq; + gd->private_data = pdisk; + + /* name this disk */ + snprintf (gd->disk_name, sizeof(gd->disk_name), "%s%c", + tffs_str, ('a' + (char)(pdisk->diskNo))); + + /* specify disk's capacity in 512-byte sectors */ + set_capacity (gd, pdisk->dwSize); + + /* Tell kernel about this disk. Before add_disk() returns, + * kernel will attempt to read Master Boot Record and parse + * partition table(s) on this disk; it will post I/O requests + * to pdisk->rq, and call disk_request_queue_handler() + * to handle these request. + */ + add_disk (gd); +} + + + + +/******************************************************************************* + * * + * c l e a n u p * + * * + * Free all data structures alocated during driver's startup. * + * * + * Parameters: * + * STEP specifies which resources to free * + * * + * Returns: void * + * * + *******************************************************************************/ +static +void cleanup ( int STEP ) +{ + int iSoc; + + if (STEP >= 8) + { +#ifdef CONFIG_PM + tffs_pm_exit (); /* unregister from Power Manager */ +#endif + } + + if (STEP >= 7) + { + /* For every socket, flush all socket's disks, and sleep until socket's + * I/O thread handled all outstanding I/O requests and exited. + */ + for (iSoc = 0; iSoc < FL_SOCKETS; iSoc++) + { + if (tffsInfo.sockets[iSoc].fFound != 0) + release_socket (&tffsInfo.sockets[iSoc]); + } + } + + if (STEP >= 6) + { +#ifdef CONFIG_PROC_FS + remove_proc_entry (tffs_str, NULL); + tffsInfo.pProcDir = NULL; +#endif + } + + if (STEP >= 5) + { + unregister_blkdev (tffs_major, tffs_str); + } + + if (STEP >= 4) + { + /* disable_irq (tffs_irq); */ + + /* We should tell DiskOnChip to disable interrupt generation, but + * unfortunately TrueFFS currently doesn't provide API for that. + */ + } + + if (STEP >= 3) + { + /* For all disks of all DiskOnChip sockets, write Quick Mount + * records to them, abs.unmount them, and shut down TrueFFS. + */ + TffsCleanup (); + } + + if (STEP >= 2) + { + /* if previously installed, remove DiskOnChip interrupt handler */ + if (tffs_irq >= 0) + free_irq (tffs_irq, &tffsInfo.sockets[0]); + } +} + + + + +/******************************************************************************* + * * + * r e l e a s e _ s o c k e t * + * * + * Release DiskOnChip socket. * + * * + * Parameters: * + * psoc pointer to socket being released * + * * + * Returns: void * + * * + *******************************************************************************/ +static +void /* __exit */ release_socket ( SocketInfo * psoc ) +{ + int iDisk; + + if (psoc->fFound == 0) + return; + + /* Release all socket's disks; this involves flushing all partitions + * on all these disks. + */ + for (iDisk = 0; iDisk < psoc->wDevices; iDisk++) + release_disk (&psoc->pDevices[iDisk]); + + if (psoc->io_thread_state == 1) /* I/O thread is running */ + { + init_completion (&psoc->wait_for_io_thread); + + /* Tell I/O thread to complete handling of all outstanding I/O requests, + * wake us up, and exit. + */ + psoc->io_thread_state = 2; + + /* in case socket's I/O thread is currently sleeping, wake it up */ + wake_up (&psoc->waitQueueHead); + + /* now wait for I/O thread to exit */ + wait_for_completion (&psoc->wait_for_io_thread); /* down_interruptible (&psoc->threadSemaphore); */ + } +} + + + + +/******************************************************************************* + * * + * r e l e a s e _ d i s k * + * * + * Release disk. * + * * + * Parameters: * + * pdisk pointer to disk being released * + * * + * Returns: void * + * * + *******************************************************************************/ +static +void /* __exit */ release_disk (DeviceInfo * pdisk) +{ + if (pdisk->gd != NULL) + { + del_gendisk (pdisk->gd); + pdisk->gd = NULL; + } + + if (pdisk->rq != NULL) + { + blk_cleanup_queue (pdisk->rq); + pdisk->rq = NULL; + } + +#ifdef CONFIG_PROC_FS + procfs_unregister (pdisk); +#endif +} + + + + +/******************************************************************************* + * * + * d i s k _ o p e n * + * * + * Open disk (i.e. block_device_operations.open()). * + * * + * Parameters: * + * * + * inode inode pointer * + * filp file pointer * + * * + * Returns: zero if success, otherwise negative error code * + * * + *******************************************************************************/ +static +int disk_open (struct block_device *bdev, + fmode_t mode) +{ + int rc = 0; /* assume success */ + struct gendisk * gd = bdev->bd_disk; + DeviceInfo * pdisk = (DeviceInfo *) gd->private_data; + + if (pdisk == NULL) + return -ENODEV; + + /* one Open/Close at a time */ + if( down_interruptible(&open_close_mutex) != 0 ) + return -ERESTARTSYS; /* wait was interrupted by signal */ + + /* can't open write-protected disk for writing */ + if (mode & O_RDWR) + { +#ifndef TFFS_RO + if( TffsIsWriteProtected(pdisk) ) +#endif + { + rc = -EROFS; goto quit; + } + } + + if (pdisk->in_use == 0) + { + if( TffsOpenDevice(pdisk) == 0 ) + { + PrintkError("Open() failed on %s(0x%x)", gd->disk_name, pdisk->bHandle); + + rc = -ENODEV; goto quit; + } + } + /* one more user for this device, as well as for DiskOnChip driver */ + pdisk->in_use++; + + quit: + + /* allow other Open/Close calls to proceed */ + up (&open_close_mutex); + + return rc; +} + + + + +/******************************************************************************* + * * + * d i s k _ c l o s e * + * * + * Release disk (i.e. block_device_operations.release()). * + * * + * Parameters: * + * * + * inode inode pointer * + * filp file pointer (could be NULL) * + * * + * Returns: zero if success, otherwise negative error code * + * * + *******************************************************************************/ +static +int disk_close (struct gendisk* gd, fmode_t mode) +{ + DeviceInfo * pdisk = (DeviceInfo *) gd->private_data; + + /* one Open/Close at a time */ + if( down_interruptible(&open_close_mutex) != 0 ) + return -ERESTARTSYS; /* wait was interrupted by signal */ + + if (--pdisk->in_use == 0) /* last user had just closed this disk */ + { + if( TffsCloseDevice(pdisk) == 0 ) + { + PrintkDebug("Release() failed on %s(0x%x)", gd->disk_name, pdisk->bHandle); + } + } + + /* allow other Open/Close calls to proceed */ + up (&open_close_mutex); + + return 0; +} + + + + +/******************************************************************************* + * * + * d i s k _ i o c t l * + * * + * Handle IOCTLs to disk (i.e. device_operations.ioctl()). * + * * + * Parameters: * + * * + * inode inode pointer * + * filp file pointer (could be NULL) * + * cmd IOCTL command * + * arg argument to IOCTL command * + * * + * Returns: zero if success, otherwise negative error code * + * * + *******************************************************************************/ +static +int disk_ioctl (struct block_device *bdev, fmode_t mode, + unsigned cmd, unsigned long arg) +{ + struct gendisk * gd = bdev->bd_disk; + DeviceInfo * pdisk = (DeviceInfo *) gd->private_data; + int rc = -ENOTTY; + + if (cmd >= SIOCDEVPRIVATE) /* driver specific (TrueFFS) IOCTL code */ + { + rc = TffsIoctl (pdisk, (cmd - SIOCDEVPRIVATE), arg); + + if (rc < 0) + PrintkError("ioctl=0x%x error=0x%x on %s", cmd, rc, gd->disk_name); + + if (rc == 1) /* unrecognized TrueFFS IOCTL code */ + rc = -ENOTTY; + } + else /* standard Linux IOCTL code */ + { + switch (cmd) + { + case HDIO_GETGEO: + { + struct hd_geometry geo; + + geo.heads = pdisk->bHead; + geo.sectors = pdisk->bSect; + geo.cylinders = pdisk->wCyl; + geo.start = get_start_sect (bdev); + + if ((void *)arg == NULL) + { rc = -EINVAL; break; } + + if( !access_ok(VERIFY_WRITE, (void *)arg, sizeof(geo))) + { rc = -EFAULT; break; } + + if( copy_to_user((void *)arg, &geo, sizeof(geo)) != 0 ) + { rc = -EFAULT; break; } + + rc = 0; /* success */ + } + break; + + default: /* unknown Linux IOCTL code */ + { + PrintkError("unknown ioctl=0x%x on %s", cmd, gd->disk_name); + } + } + } + + return rc; +} + + + + +/******************************************************************************* + * * + * i n t e r r u p t _ h a n d l e r * + * * + * DiskOnChip interupt handler. * + * * + * Parameters: * + * * + * irq not used * + * psoc socket pointer * + * regs not used * + * * + * Returns: always IRQ_HANDLED * + * * + *******************************************************************************/ +static +irqreturn_t interrupt_handler ( int irq, /* not used */ + void * psoc) /* not used */ +{ +// tffs_irq_disable (FALSE); + + profiling[1]++; + + /* wake up socket's I/O thread */ + complete (&((SocketInfo *)psoc)->wait_for_irq); /* up (&((SocketInfo *)psoc)->sleep_sem); */ + return IRQ_HANDLED; +} + + + + +/******************************************************************************* + * * + * t f f s _i r q _ e n a b l e * + * * + * Enable IRQ that DiskOnChip is connected to. * + * * + * Parameters: * + * * + * lock if TRUE, use __irq_lock; otherwise don't * + * * + *******************************************************************************/ +void tffs_irq_enable (int lock) +{ + enable_irq (tffs_irq); +} + + + +/******************************************************************************* + * * + * t f f s _i r q _ d i s a b l e * + * * + * Disable IRQ that DiskOnChip is connected to. * + * * + * Parameters: * + * * + * lock if TRUE, use __irq_lock; otherwise don't * + * * + *******************************************************************************/ +void tffs_irq_disable (int lock) +{ + disable_irq (tffs_irq); +} + + + + +/******************************************************************************* + * * + * d i s k _ r e q u e s t _ q u e u e _ h a n d l e r * + * * + * This routine implements request handling function for per-disk request * + * queue. It's called by generic_unplug_device (drivers/block/ll_rw_block.c) * + * with request queue's lock held, and both hardware and software interrupts * + * disabled (so it must be fast). * + * * + * Parameters: * + * q disk's request queue * + * * + *******************************************************************************/ +static +void disk_request_queue_handler (struct request_queue * q) +{ + struct request * r; + SocketInfo * psoc; + DeviceInfo * pdisk; + int lock_taken = FALSE; + + /* we run with hardware and software interrupts disabled */ + + + while (1) + { + /* take this request off disk's request queue */ + r = blk_fetch_request(q); + if (NULL == r) break; + if (lock_taken == FALSE) + { + pdisk = r->rq_disk->private_data; + psoc = pdisk->pSocket; + + spin_lock (&psoc->request_list_lock); + lock_taken = TRUE; + } + + /* Append this request to socket's request list. Socket's + * I/O thread will take it from there, handle it, and cycle + * it back to this queue. + */ + list_add_tail (&r->queuelist, &psoc->requestsList); + } + + if (lock_taken == TRUE) + { + spin_unlock (&psoc->request_list_lock); + + /* in case socket's I/O thread is currently sleeping, wake it up */ + wake_up (&psoc->waitQueueHead); + } +} + + + + +/******************************************************************************* + * * + * s o c k e t _ i o _ t h r e a d * + * * + * This routine implements per-socket I/O thread. It runs as a kernel thread, * + * and processes I/O requests that disk_request_queue_handler() put to * + * socket's request list. This routine can (and often does) sleep. * + * * + * Parameters: * + * arg socket pointer * + * * + *******************************************************************************/ +static +int socket_io_thread (void * arg) +{ + SocketInfo * psoc = (SocketInfo *) arg; + char name[32]; + + current->flags |= (PF_MEMALLOC | PF_NOFREEZE); + + sprintf (name, "%s%c", tffs_str, '0' + (char)psoc->bHandle); + daemonize (name); + + /* we don't want to receive any signals */ + spin_lock_irq (¤t->sighand->siglock); + sigfillset (¤t->blocked); + recalc_sigpending (); + spin_unlock_irq (¤t->sighand->siglock); + + /* adjist thread's priority if necessary */ + if (tffs_prio != 0) + set_user_nice (current, tffs_prio); + + /* initially socket's request list is empty */ + spin_lock_init (&psoc->request_list_lock); + INIT_LIST_HEAD (&psoc->requestsList); + + /* If somebody is waiting for socket's I/O thread to start up and + * get ready for processing I/O requests, let them know that we did. + */ + if (psoc->io_thread_state == 2) + complete (&psoc->wait_for_io_thread); /* up (&psoc->threadSemaphore); */ + + /* socket's I/O thread is ready to receive I/O requests */ + psoc->io_thread_state = 1; + + while (psoc->io_thread_state == 1) + { + /* wait 5 clock ticks for I/O requests to arrive */ + wait_event_interruptible_timeout (psoc->waitQueueHead, requests_to_do(psoc), 5); + + /* handle all I/O requests (if any) in socket's request ist */ + do_requests_list (psoc); + } + + /* If somebody is waiting for socket's I/O thread to terminate, + * let them know that it did. + */ + if (psoc->io_thread_state == 2) + complete (&psoc->wait_for_io_thread); /* up (&psoc->threadSemaphore); */ + + /* socket's I/O thread terminated */ + psoc->io_thread_state = 0; + + return 0; +} + + + + +/******************************************************************************* + * * + * d o _ r e q u e s t s _ l i s t * + * * + * This routine handles all requests in socket's request list. * + * * + * Parameters: * + * psoc socket pointer * + * * + *******************************************************************************/ +static +void do_requests_list ( SocketInfo * psoc ) +{ + struct request * r; + struct gendisk * gd; + DeviceInfo * pdisk; + unsigned long flags; + + /* lock socket's request list */ + spin_lock_irqsave (&psoc->request_list_lock, flags); + + /* if socket's request list isn't empty, process all requests there */ + while( !(list_empty(&psoc->requestsList)) ) + { + int err = -EIO; + /* take next request off socket's request list */ + r = list_entry_rq (psoc->requestsList.next); + list_del_init (&r->queuelist); + + /* unlock socket's request list */ + spin_unlock_irqrestore (&psoc->request_list_lock, flags); + + /* Mark all non-filesystem request, and those filesystem requests + * that don't pass sanity check, as not-uptodate (i.e. failed). + */ + if( !blk_fs_request(r) || + ((gd = r->rq_disk) == NULL) || + ((pdisk = gd->private_data) == NULL) || + (pdisk->gd != gd) || + (blk_rq_pos(r) + blk_rq_sectors(r) > pdisk->dwSize) + ) + { + } + else /* legitimate filesystem request; handle it */ + { + int success; + if (rq_data_dir(r) == WRITE) + { + write_requests++; + + success = do_write_request (r); + } + else /* READ request */ + { + success = do_read_request (r); + } + if (success) { + err = 0; + } + } + + /* mark this request as done */ + blk_end_request_all(r, err); + + /* lock socket's request list */ + spin_lock_irqsave (&psoc->request_list_lock, flags); + } + + /* unlock socket's request list */ + spin_unlock_irqrestore (&psoc->request_list_lock, flags); +} + + + + +/******************************************************************************* + * * + * d o _ w r i t e _ r e q u e s t * + * * + * This routine handles single WRITE request. * + * * + * Parameters: * + * psoc socket pointer * + * * + * Returns: * + * zero if I/O error was encountered, otherwise '1'. * + * * + *******************************************************************************/ +static +int do_write_request ( struct request * r ) +{ + DeviceInfo * pdisk = (DeviceInfo *) r->rq_disk->private_data; + struct bio * bio; + struct gather_t gather; + unsigned long total_sectors = blk_rq_sectors(r); + int success = 1; + + /* in case we are going to use gather buffer, mark it as empty */ + if ((tffs_sg_bufsize > 0) && (tffs_sg_write != FALSE)) + { + gather.buf = + gather.free = pdisk->pSocket->pCache; + gather.size = + gather.free_bytes = tffs_sg_bufsize; + + /* first disk sector # for this request */ + gather.start_sector = blk_rq_pos(r); + } + + /* do all bio's of this request */ + // @todo use rq_for_each_segment + __rq_for_each_bio (bio, r) + { + if( write_bio(bio, &gather, pdisk) < 0) + success = 0; /* I/O error */ + } + + /* flush remaining data (if any) from gather buffer to disk */ + if ((tffs_sg_bufsize > 0) && (tffs_sg_write != FALSE) + && (gather.free > gather.buf)) + { + int ns = ((gather.free - gather.buf) >> 9); /* remaining sectors in buf */ + + if( TffsWrite (pdisk, gather.buf, gather.start_sector, ns) == 0 ) + success = 0; /* I/O error */ + } + return success; +} + + + + +/******************************************************************************* + * * + * d o _ r e a d _ r e q u e s t * + * * + * This routine handles single READ request. * + * * + * Parameters: * + * psoc socket pointer * + * * + * Returns: * + * zero if I/O error was encountered, otherwise '1'. * + * * + *******************************************************************************/ +static +int do_read_request ( struct request * r ) +{ + DeviceInfo * pdisk = (DeviceInfo *) r->rq_disk->private_data; + struct bio * bio; + struct scatter_t scatter; + unsigned long total_sectors = blk_rq_sectors(r); + int success = 1; + + /* read in data from disk into scatter buffer */ + if ((tffs_sg_bufsize > 0) && (tffs_sg_read != FALSE)) + { + int ns = _MIN(blk_rq_sectors(r), (tffs_sg_bufsize >> 9)); + + scatter.buf = pdisk->pSocket->pCache; + scatter.size = tffs_sg_bufsize; + + if( TffsRead (pdisk, scatter.buf, blk_rq_pos(r), ns) == 0 ) + { + success = 0; /* I/O error */ + goto out; + } + + scatter.pcurrent = scatter.buf; + scatter.remaining_bytes = (ns << 9); + scatter.sectors = blk_rq_sectors(r) - ns; + scatter.start_sector = blk_rq_pos(r) + ns; + } + + /* do all bio's of this request */ + __rq_for_each_bio (bio, r) + { + if( read_bio(bio, &scatter, pdisk) < 0) + success = 0; /* I/O error */ + } + +out: + return success; +} + + + + +/******************************************************************************* + * * + * w r i t e _ b i o * + * * + * This routine handles single 'struct bio' WRITE operation using gather * + * buffer. * + * * + * Parameters: * + * bio pointer to 'struct bio' to WRITE * + * gather pointer to gather buffer * + * pdisk disk pointer * + * * + * Returns: * + * zero if success otherwise -EIO negative error code * + * * + *******************************************************************************/ +static +int write_bio ( struct bio * bio, + struct gather_t * gather, + DeviceInfo * pdisk ) +{ + struct bio_vec * bv; + int i, rc = 0; + + if ((tffs_sg_bufsize == 0) || (tffs_sg_write == FALSE)) + { + /* we don't use gather buffer; do one I/O segment at a time */ + rc = rw_bio_no_sg (bio, pdisk, WRITE); + } + else /* use gather buffer */ + { + bio_for_each_segment (bv, bio, i) + { + unsigned int n = bv->bv_len; /* bytes in this I/O segment */ + char * p; + + /* If segment's page resides in high memory, map it into + * kernel's address space temporarily. + */ + if (PageHighMem(bv->bv_page)) + p = kmap (bv->bv_page) + bv->bv_offset; + else /* segment's page resides in low memory */ + p = page_address (bv->bv_page) + bv->bv_offset; + + for (; n >= gather->free_bytes; ) + { + /* This I/O segment won't fit into the remaining space in + * gather buffer. Copy the part that does fit into gather + * buffer (making it full), then flush entire gather buffer + * to disk. + */ + if (gather->free_bytes > 0) + { + memcpy (gather->free, p, gather->free_bytes); + + p += gather->free_bytes; + n -= gather->free_bytes; + } + + /* flush entire gather buffer to disk */ + if( TffsWrite (pdisk, gather->buf, gather->start_sector, + (gather->size >> 9)) == 0 ) + rc = -EIO; /* I/O error */ + + /* gather buffer is empty */ + gather->free = gather->buf; + gather->free_bytes = gather->size; + gather->start_sector += (gather->size >> 9); + } + + /* remaining part of this segment fits into gather buffer */ + if (n > 0) + { + memcpy (gather->free, p, n); + + gather->free += n; + gather->free_bytes -= n; + } + + /* If segment's page resides in high memory, cancel + * previously established mapping. + */ + if (PageHighMem(bv->bv_page)) + kunmap (bv->bv_page); + } + } + + return rc; +} + + + + +/******************************************************************************* + * * + * r e a d _ b i o * + * * + * This routine handles single 'struct bio' READ operation using scatter * + * buffer. * + * * + * Parameters: * + * bio pointer to 'struct bio' to WRITE * + * scatter pointer to scatter buffer * + * pdisk disk pointer * + * * + * Returns: * + * zero if success otherwise -EIO negative error code * + * * + *******************************************************************************/ +static +int read_bio ( struct bio * bio, + struct scatter_t * scatter, + DeviceInfo * pdisk ) +{ + struct bio_vec * bv; + int i, rc = 0; + + if ((tffs_sg_bufsize == 0) || (tffs_sg_read == FALSE)) + { + /* we don't use scatter buffer; do one I/O segment at a time */ + rc = rw_bio_no_sg (bio, pdisk, READ); + } + else /* use gather buffer */ + { + bio_for_each_segment (bv, bio, i) + { + unsigned int n = bv->bv_len; /* bytes in this I/O segment */ + unsigned int ns; + char * p; + + /* If segment's page resides in high memory, map it into + * kernel's address space temporarily. + */ + if (PageHighMem(bv->bv_page)) + p = kmap (bv->bv_page) + bv->bv_offset; + else /* segment's page resides in low memory */ + p = page_address (bv->bv_page) + bv->bv_offset; + + for (; n >= scatter->remaining_bytes; ) + { + /* This I/O segment is larger then number of remaining bytes + * in scatter buffer. Copy all these remaining bytes (making + * scatter buffer empty), then re-fill scatter buffer from disk. + */ + if (scatter->remaining_bytes > 0) + { + memcpy (p, scatter->pcurrent, scatter->remaining_bytes); + + p += scatter->remaining_bytes; + n -= scatter->remaining_bytes; + } + + /* scatter buffer is empty now */ + scatter->remaining_bytes = 0; + scatter->pcurrent = scatter->buf; + + /* end of this request ? */ + if ((ns = _MIN(scatter->sectors, (tffs_sg_bufsize >> 9))) == 0) + break; + + /* re-fill scatter buffer from disk */ + if( TffsRead (pdisk, scatter->buf, scatter->start_sector, ns) == 0 ) + rc = -EIO; /* I/O error */ + + scatter->remaining_bytes = (ns << 9); + scatter->sectors -= ns; + scatter->start_sector += ns; + } + + /* Remaining part of this segment can be entirely taken + * from the scatter buffer. + */ + if (n > 0) + { + memcpy (p, scatter->pcurrent, n); + + scatter->pcurrent += n; + scatter->remaining_bytes -= n; + } + + /* If segment's page resides in high memory, cancel + * previously established mapping. + */ + if (PageHighMem(bv->bv_page)) + kunmap (bv->bv_page); + } + } + + return rc; +} + + + + +/******************************************************************************* + * * + * r w _ b i o _ n o _ s g * + * * + * This routine handles single 'struct bio' without using scatter/gather * + * buffers. It issues TrueFFS I/O call for each segment of this 'struct bio'. * + * * + * Parameters: * + * bio pointer to 'struct bio' to handle * + * pdisk disk pointer * + * rw READ or WRITE * + * * + * Returns: * + * zero if success otherwise -EIO negative error code * + * * + *******************************************************************************/ +static +int rw_bio_no_sg ( struct bio * bio, + DeviceInfo * pdisk, + int rw ) +{ + sector_t sector = bio->bi_sector; /* starting disk sector for this bio */ + struct bio_vec * bv; + char * p; + int i, rc = 0; + unsigned int ns; + + bio_for_each_segment (bv, bio, i) + { + if ((ns = (bv->bv_len >> 9)) > 0) /* sectors in this segment */ + { + /* If segment's page resides in high memory, map it into + * kernel's address space temporarily. + */ + if (PageHighMem(bv->bv_page)) + p = kmap (bv->bv_page) + bv->bv_offset; + else /* segment's page resides in low memory */ + p = page_address (bv->bv_page) + bv->bv_offset; + + if (rw == READ) + { + if( TffsRead (pdisk, p, sector, ns) == 0 ) + rc = -EIO; /* I/O error */ + } + else + { + if( TffsWrite (pdisk, p, sector, ns) == 0 ) + rc = -EIO; /* I/O error */ + } + + /* If segment's page resides in high memory, cancel + * previously established mapping. + */ + if (PageHighMem(bv->bv_page)) + kunmap (bv->bv_page); + + sector += ns; + } + } + + return rc; +} + + + + +/******************************************************************************* + * * + * r e q u e s t s _ t o _ d o * + * * + * This routine checks if there are any requests in socket's request list. * + * * + * Parameters: * + * psoc socket pointer * + * * + * Returns: * + * FALSE if list is empty, otherwise TRUE * + * * + *******************************************************************************/ +static +int requests_to_do ( SocketInfo * psoc ) +{ + unsigned long flags; + int rc = FALSE; /* assume list is empty */ + + spin_lock_irqsave (&psoc->request_list_lock, flags); + + if( !list_empty(&psoc->requestsList) ) + rc = TRUE; + + spin_unlock_irqrestore (&psoc->request_list_lock, flags); + + return rc; +} + + + +/******************************************************************************* + * * + * t f f s _ s u s p e n d * + * * + * This routine is intended to be called by various Linux Power Managers to * + * power down all DiskOnChip devices when system goes into powerdown mode. * + * * + * Parameters: none * + * * + * Returns: void * + * * + *******************************************************************************/ +void tffs_suspend (void) +{ + SocketInfo * psoc; + int i; + + for (i = 0; i < FL_SOCKETS; i++) + { + psoc = &tffsInfo.sockets[i]; + + if (psoc->fFound == 0) + continue; + + init_completion (&psoc->wait_for_io_thread); + + /* Tell I/O thread to finish all outstanding I/O requests, wake + * up us, and exit. + */ + psoc->io_thread_state = 2; + + /* in case socket's I/O thread is currently sleeping, wake it up */ + wake_up (&psoc->waitQueueHead); + + /* wait for I/O thread to exit */ + wait_for_completion (&psoc->wait_for_io_thread); /* down_interruptible (&psoc->threadSemaphore); */ + + /* tell TrueFFS to power down DiskOnChip */ + TffsSuspend (psoc); + } + + /* disable DiskOnChip interrupts */ + if (tffs_irq >= 0) + { + tffs_irq_disable (TRUE); + } +} + + + + +/******************************************************************************* + * * + * t f f s _ r e s u m e * + * * + * This routine is intended to be called by various Linux Power Managers to * + * power up all DiskOnChip devices when system comes up from powerdown mode. * + * * + * Parameters: none * + * * + * Returns: void * + * * + *******************************************************************************/ +void tffs_resume (void) +{ + SocketInfo * psoc; + int i; + + /* We are doing 'resume' after previous power 'suspend', not + * full scale board initialization, hence TRUE flag below. + */ + tffsarch_init (TRUE); + + /* enable DiskOnChip interrupts */ + if (tffs_irq >= 0) + { + tffs_irq_enable (TRUE); + } + + for (i = 0; i < FL_SOCKETS; i++) + { + psoc = &tffsInfo.sockets[i]; + + if (psoc->fFound == 0) + continue; + + /* Tell TrueFFS to power up DiskOnChip. This call takes around 20 + * milliseconds (DiskOnChip driver will not yield CPU during this time). + */ + TffsResume (psoc); + + /* restore multi-sector poleld I/O mode in DiskOnChip h3 devices */ + TffsSetPIO (psoc); + + init_completion (&psoc->wait_for_io_thread); + + /* tell I/O thread to wake us up once it gets running */ + psoc->io_thread_state = 2; + + /* start I/O thread */ + kernel_thread (socket_io_thread, (void *)psoc, 0); + + /* wait for I/O thread to get running */ + wait_for_completion (&psoc->wait_for_io_thread); /* down_interruptible (&psoc->threadSemaphore); */ + } +} + + + + +#ifdef CONFIG_PROC_FS + +/******************************************************************************* + * * + * p r o c f s _ r e g i s t e r * + * * + * Create disk's entry in /proc/. * + * * + * Parameters: * + * * + * pdisk disk pointer * + * * + * Returns: zero if success otherwise negative error code. * + * * + *******************************************************************************/ +static +int /* __init */ procfs_register ( DeviceInfo * pdisk ) +{ + char name[] = "a"; + + name[0] += (char)(pdisk->diskNo); + + if ((pdisk->pProcFile = create_proc_entry(name, 0, tffsInfo.pProcDir)) == NULL) + { + PrintkWarning("Can't create /proc/tffs/%s", name); + return -EBUSY; + } + + pdisk->pProcFile->read_proc = procfs_read; + pdisk->pProcFile->write_proc = procfs_write; + pdisk->pProcFile->data = pdisk; + + return 0; +} + + + + +/******************************************************************************* + * * + * p r o c f s _ u n r e g i s t e r * + * * + * Delete disk's entry in /proc/. * + * * + * Parameters: * + * * + * pdisk disk pointer * + * * + * Returns: always zero (success). * + * * + *******************************************************************************/ +static +int /* __exit */ procfs_unregister ( DeviceInfo * pdisk ) +{ + char name[] = "a"; + + name[0] += (char)(pdisk->diskNo); + + remove_proc_entry (name, tffsInfo.pProcDir); + pdisk->pProcFile = NULL; + + return 0; +} + + + + +/******************************************************************************* + * * + * p r o c f s _ w r i t e * + * * + * Called when disk's entry in /proc/ is wriiten to. * + * * + * Parameters: * + * * + * file not used * + * buffer not used * + * count not used * + * data disk pointer * + * * + * Returns: always zero (success). * + * * + *******************************************************************************/ +static +int procfs_write ( struct file * file, + const char * buffer, + unsigned long count, + void * data ) +{ +# ifdef TFFS_STATISTIC + DeviceInfo * pdisk = (DeviceInfo *)data; + + memset (&pdisk->stat, 0, sizeof(pdisk->stat)); +# endif + + return count; +} + + + + +/******************************************************************************* + * * + * p r o c f s _ r e a d * + * * + * Called when disk's entry in /proc/ is read from. * + * * + * Parameters: * + * * + * buf buffer to put data to * + * start not used * + * offset not used * + * length not used * + * eof End-of-File indicator * + * data disk pointer * + * * + * Returns: number of characters written to buffer 'buf' * + * * + *******************************************************************************/ +static +int procfs_read ( char * buf, + char ** start, + off_t offset, + int length, + int * eof, + void * data ) +{ + char * p = buf; + int i; + +# ifdef TFFS_STATISTIC + + { DeviceInfo * pdisk = (DeviceInfo *)data; + TffsStatistic * stat = &pdisk->stat; + + p += sprintf (p, "flAbsRead calls %ld\n", stat->dwAbsRead); + p += sprintf (p, "total %ld read requests (%ld by disk_request_queue_handler)\n", + stat->dwReadReq, stat->dwReadReqNoThread); + p += sprintf (p, "total %ld sectors read (aligned %ld, unaligned %ld)\n", + stat->dwAbsReadSec, stat->dwAlReadSec, stat->dwUnalReadSec); + p += sprintf (p, "read shared sectors: aligned %ld, unaligned %ld\n", + stat->dwAlReadShared, stat->dwUnalReadShared); + + p += sprintf (p,"flAbsWrite calls %ld\n", stat->dwAbsWrite); + p += sprintf (p, "total %ld write requests\n", stat->dwWriteReq); + p += sprintf (p,"total %ld sectors written (aligned %ld, unaligned %ld)\n", + stat->dwAbsWriteSec, stat->dwAlWriteSec, stat->dwUnalWriteSec); + p += sprintf (p,"written shared sectors: aligned %ld, unaligned %ld\n", + stat->dwAlWriteShared, stat->dwUnalWriteShared); + } + +# endif /* TFFS_STATISTIC */ + + p += sprintf (p, "profiling:"); + for (i = 0; i < 10; i++) + p += sprintf (p, " %d", profiling[i]); + p += sprintf (p, "\n"); + + *eof = 1; + + return (p - buf); +} + +#endif /* CONFIG_PROC_FS */ + +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) */ + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/tffsdrv.h linux-2.6.30.4/drivers/block/tffs/tffsdrv.h --- linux-2.6.30.4-orig/drivers/block/tffs/tffsdrv.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/tffsdrv.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,307 @@ +/****************************************************************************** + * * + * Project: DOC Driver for Linux 2.6 Block device driver for mDOC H3 family * + * of devices under Linux kernel 2.6. * + * * + * Version: 1.0 * + * Email questions to: oemsupport@sandisk.com * + * Copyright (C) SanDisk IL Ltd. 1995 - 2007 * + * SanDisk IL Ltd., 7 Atir Yeda Street, Kfar Saba 44425, Israel * + * * + ****************************************************************************** + * * + * 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 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, which is set forth in the readme.txt file. * + * 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., 51 * + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + * * + * This License does not grant you any right to use the trademarks, service * + * marks or logos of SanDisk IL Ltd. or SanDisk Corporation. * + * Subject to the foregoing, SanDisk IL Ltd., for itself and on behalf of its * + * licensors, hereby reserves all intellectual property rights in the program,* + * except for the rights expressly granted in this License. * + * * + ******************************************************************************/ + +/* + * $Log$ + */ + + +#ifndef __TFFSDRV_H__ +#define __TFFSDRV_H__ + +/* this driver is for 2.[4/5/6].x versions of Linux kernels */ +#include +#ifndef KERNEL_VERSION +# define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) +#endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,7,0)) || (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)) +# error "unsupported Linux kernel version" +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) +# include +#endif + +#if (LINUX_VERSION_CODE +# else +# include +# endif +# endif +#endif + +#include + +#if (LINUX_VERSION_CODE>KERNEL_VERSION(2,5,0)) +# include +#endif + +#include /* kmalloc() */ +#include /* HDIO_GETGEO */ +#include /* ...lock_kernel() */ +#include /* ...mem_region() */ +#include +#include /* ok_access(), put_usr(), get_user() */ +#include +#include /* struct ext2_super_block */ /* only for ext filter */ +#include /* mdelay() */ +#include +#include +#include /* blk_ioctl() */ +#include /* for SIOCDEVPRIVATE */ /* only for 2.6.x */ +#include /* 2.4.18 for lubbock don't want to work w/o this */ +#include +#include +#include +#include + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) +# include +# include +#endif + +#include "flcustom.h" +#include "tffsarch.h" + +#ifdef CONFIG_PROC_FS +# include +#endif + +/* definitions for blk.h */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) +extern int tffs_major; +# define MAJOR_NR tffs_major +# define DEVICE_ON +# define DEVICE_OFF(d) +# define DEVICE_NR(device) (MINOR(device)>>DEV2PART_SHIFT) +# define DEVICE_NO_RANDOM +# include +#else +# include +#endif +/* end of blk.h definitions */ + +#ifdef TFFS_DEBUG_DRIVER +# define PrintkDebug(fmt,args...) printk(KERN_DEBUG TFFS_DEVICE_NAME": "fmt"\n",## args) +/* # define PrintkDebug(fmt,args...) printk(KERN_ERR TFFS_DEVICE_NAME": "fmt"\n",## args) */ +#else /* TFFS_DEBUG_DRIVER */ +# define PrintkDebug(fmt,args...) +#endif /* TFFS_DEBUG_DRIVER */ +#define PrintkInfo(fmt,args...) printk(KERN_INFO TFFS_DEVICE_NAME": "fmt"\n",## args) +#define PrintkError(fmt,args...) printk(KERN_ERR TFFS_DEVICE_NAME": "fmt"\n",## args) +#define PrintkWarning(fmt,args...) printk(KERN_WARNING TFFS_DEVICE_NAME": "fmt"\n",## args) + +#ifdef TFFS_STATISTIC + +typedef struct +{ + unsigned long dwReadReq; /* total 'read' requests received by driver */ + unsigned long dwReadReqNoThread; /* number of these requests done by DeviceRequest() */ + unsigned long dwAbsReadSec; /* total sectors read */ + unsigned long dwAlReadSec; /* aligned 512-byte sectors read */ + unsigned long dwUnalReadSec; /* unaligned 512-byte sectors read */ + unsigned long dwAlReadShared; /* aligned shared 512-byte sectors read */ + unsigned long dwUnalReadShared; /* unaligned shared 512-byte sectors read */ + unsigned long dwAbsRead; /* total flAbsRead() calls */ + unsigned long dwWriteReq; /* total 'write' requests received by driver */ + unsigned long dwAbsWriteSec; /* total sectors written */ + unsigned long dwAlWriteSec; /* aligned 512-byte sectors written */ + unsigned long dwUnalWriteSec; /* unaligned 512-byte sectors written */ + unsigned long dwAlWriteShared; /* aligned shared 512-byte sectors written */ + unsigned long dwUnalWriteShared; /* unaligned shared 512-byte sectors written */ + unsigned long dwAbsWrite; /* total flAbsWrite() calls */ +}TffsStatistic; + +#endif /* TFFS_STATISTIC */ + +struct tagDeviceInfo; + +typedef struct +{ + struct tagDeviceInfo*pDevices; + unsigned short wDevices; /* should be WORD to allow left shift to 5 */ + struct list_head requestsList; /* list of requests from IO queue */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) + spinlock_t request_list_lock; +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) + struct completion wait_for_io_thread; /* wait for socket's I/O thread to start/stop */ + struct completion wait_for_irq; /* wait for DiskOnChip interrupt */ +#else + struct semaphore threadSemaphore; /* wait for socket's I/O thread to start/stop */ + struct semaphore sleep_sem; /* used to wait for erase/write completion */ +#endif + + wait_queue_head_t waitQueueHead; /* wait queue for thread and flSleep */ + int io_thread_state; + unsigned char bHandle; /* socket, as ioreq.irHandle */ + char * pCache; + int fFound; + unsigned long dwPhysAddr,dwVirtAddr,dwMappedLen; + int fMemRequested; +}SocketInfo; + +/* #ifdef TFFS_USE_EXT_FILTER */ +struct tagSectInfo; +typedef struct tagSectInfo +{ + unsigned long dwSector; /* no of sector on device */ + unsigned short bSectors; /* length */ + struct tagSectInfo*pParent,*pPrev,*pNext; + unsigned char bFlag; +#define EXTF_PT 0x01 /* empty part table space */ +#define EXTF_HAS_PT 0x02 /* has written part table */ +#define EXTF_SB 0x04 /* empty super block space */ +#define EXTF_HAS_SB 0x08 /* has superblock written, but no group descriptors */ +#define EXTF_HAS_GD 0x10 /* has superblock and group descriptors */ +#define EXTF_BB 0x20 /* block bitmap was allocated and waiting for group description */ +#define EXTF_HAS_BB 0x40 /* has block bitmap */ +#ifdef TFFS_DEBUG_DRIVER + int no; /* part no */ + unsigned long dwOffset; /* PT */ + unsigned long dwFirstSectorOfBitmap; /* BB */ + unsigned long dwExt3Flags; /* SB */ +#else + unsigned long dw; +#define dwOffset dw +#define dwFirstSectorOfBitmap dw +#define dwExt3Flags dw +#endif /* TFFS_DEBUG_DRIVER */ + unsigned long dwBlocksPerBitmap; /* SB and BB */ + unsigned char bSect2BlockShift; /* SB */ + unsigned short wGroups; /* SB */ +}SectInfo; +/* #endif TFFS_USE_EXT_FILTER */ + +typedef struct tagDeviceInfo +{ + SocketInfo*pSocket; + unsigned char diskNo; /* disk # (zero-based) */ + unsigned char bHandle; /* socket & partition, as ioreq.irHandle */ + unsigned long dwSize; /* device size */ + int in_use; + unsigned short wHWSectorSize; /* hw sector size in driver */ + unsigned short wTffsHWSectorSizeShift; /* shared sectors size in tffs */ + unsigned char fAbsMounted; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) + struct gendisk * gd; /* struct gendisk allocated for this disk */ + struct request_queue * rq; /* disk's request queue */ + spinlock_t rq_lock; /* request queue lock */ +#else + request_queue_t requestQueue; +#endif + +/* #ifdef TFFS_USE_EXT_FILTER */ + SectInfo sect[2]; + SectInfo **pCache; +/* #endif */ + + unsigned short wCyl; + unsigned char bHead,bSect; + +#ifdef TFFS_STATISTIC + TffsStatistic stat; /* various disk statistics */ +#endif + +#ifdef CONFIG_PROC_FS + struct proc_dir_entry * pProcFile; +#endif +}DeviceInfo; + +typedef struct +{ + unsigned char wDevices; + SocketInfo sockets[FL_SOCKETS]; + DeviceInfo*ppDevices[FL_VOLUMES]; + +#if defined(TFFS_PARTITIONABLE) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) + struct gendisk genDisk; +#endif + +#ifdef CONFIG_PROC_FS + struct proc_dir_entry*pProcDir; +#endif + + int channel; /* assume only one DMA connected */ + dma_addr_t dma_buf_paddr; /* physical address of DMA buffer */ + void * dma_buf_vptr; /* virtual address of DMA buffer */ + int dma_buf_size; /* size of DMA buffer in bytes */ + +}TffsInfo; + +extern TffsInfo tffsInfo; +extern int tffs_sg_bufsize; + +#define VMalloc(size) vmalloc((size)+4) +#define KMalloc(size) kmalloc((size)+4,GFP_KERNEL) + +/* DiskOnChip driver's minor version number */ +#define TFFS_DRV_VER 86 + + +/* driver's generic suspend/resume power management routines */ +extern void tffs_suspend (void); +extern void tffs_resume (void); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) +# ifdef CONFIG_PM +# include + extern int tffs_pm_init (void); + extern int tffs_pm_exit (void); + extern int tffs_pm_allowed (SocketInfo * pSoc, int flag); +# endif + +# ifdef CONFIG_DPM +# include + extern int tffs_dpm_register (void); + extern int tffs_dpm_unregister (void); +# endif +#endif + + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) && defined (CONFIG_PM) +# include +# if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) +# include +# endif + extern int tffs_pm_init (void); + extern int tffs_pm_exit (void); +#endif + + +#endif /* __TFFSDRV_H__*/ diff -urN linux-2.6.30.4-orig/drivers/block/tffs/_tffsioct.h linux-2.6.30.4/drivers/block/tffs/_tffsioct.h --- linux-2.6.30.4-orig/drivers/block/tffs/_tffsioct.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/_tffsioct.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,79 @@ +/****************************************************************************** + * * + * Project: DOC Driver for Linux 2.6 Block device driver for mDOC H3 family * + * of devices under Linux kernel 2.6. * + * * + * Version: 1.0 * + * Email questions to: oemsupport@sandisk.com * + * Copyright (C) SanDisk IL Ltd. 1995 - 2007 * + * SanDisk IL Ltd., 7 Atir Yeda Street, Kfar Saba 44425, Israel * + * * + ****************************************************************************** + * * + * 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 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, which is set forth in the readme.txt file. * + * 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., 51 * + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + * * + * This License does not grant you any right to use the trademarks, service * + * marks or logos of SanDisk IL Ltd. or SanDisk Corporation. * + * Subject to the foregoing, SanDisk IL Ltd., for itself and on behalf of its * + * licensors, hereby reserves all intellectual property rights in the program,* + * except for the rights expressly granted in this License. * + * * + ******************************************************************************/ + +/* + * $Log$ + */ + + +#ifndef __TFFSIOCT_H +#define __TFFSIOCT_H + + +typedef struct +{ + unsigned long command; + unsigned long data; +}flInputLnxRecord; + + +typedef struct +{ + unsigned long status; + unsigned long data; +} flOutputLnxRecord; + + +/* replicas of structures in doch_api.h */ + +typedef struct { unsigned char bFeaturesError; + unsigned char bSectorCount; + unsigned char bSectorNumber; + unsigned char bCylLow; + unsigned char bCylHigh; + unsigned char bDriveHead; + unsigned char bCommandStatus; + unsigned char bContorlAltStatus; + } flDochRegisters; + +typedef struct { int socketNum; + int passThruOP; + flDochRegisters in_regs; + flDochRegisters out_regs; + unsigned int secNum; + void *userBuff; + unsigned long userBuffSize; + int status; + } flAtaPassthrough; + + +#endif /* __TFFSIOCT_H */ + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/tffsioct.h linux-2.6.30.4/drivers/block/tffs/tffsioct.h --- linux-2.6.30.4-orig/drivers/block/tffs/tffsioct.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/tffsioct.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,55 @@ +/****************************************************************************** + * * + * Project: DOC Driver for Linux 2.6 Block device driver for mDOC H3 family * + * of devices under Linux kernel 2.6. * + * * + * Version: 1.0 * + * Email questions to: oemsupport@sandisk.com * + * Copyright (C) SanDisk IL Ltd. 1995 - 2007 * + * SanDisk IL Ltd., 7 Atir Yeda Street, Kfar Saba 44425, Israel * + * * + ****************************************************************************** + * * + * 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 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, which is set forth in the readme.txt file. * + * 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., 51 * + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + * * + * This License does not grant you any right to use the trademarks, service * + * marks or logos of SanDisk IL Ltd. or SanDisk Corporation. * + * Subject to the foregoing, SanDisk IL Ltd., for itself and on behalf of its * + * licensors, hereby reserves all intellectual property rights in the program,* + * except for the rights expressly granted in this License. * + * * + ******************************************************************************/ + +/* + * $Log$ + */ + + +#ifndef TFFSIOCT_H +#define TFFSIOCT_H + +#include "_tffsioct.h" +#include + + +#define FL_IOCTL_LNX (SIOCDEVPRIVATE + 0) +#define FL_IOCTL_START (SIOCDEVPRIVATE + 1) + +#include "flioctl.h" + +/* replicas of enums in doch_api.h */ +#define DOCH_PASSTHRU_DATA_OUT 0x02 +#define DOCH_DOWNLOAD_MICROCODE 0x92 +#define DOCH_DLMCODE_DOWNLOAD_AND_SAVE 0x7 + +#endif /* TFFSIOCT_H */ + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/tffs.mod.c linux-2.6.30.4/drivers/block/tffs/tffs.mod.c --- linux-2.6.30.4-orig/drivers/block/tffs/tffs.mod.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/tffs.mod.c 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,21 @@ +#include +#include +#include + +MODULE_INFO(vermagic, VERMAGIC_STRING); + +#undef unix +struct module __this_module +__attribute__((section(".gnu.linkonce.this_module"))) = { + .name = __stringify(KBUILD_MODNAME), + .init = init_module, +#ifdef CONFIG_MODULE_UNLOAD + .exit = cleanup_module, +#endif +}; + +static const char __module_depends[] +__attribute_used__ +__attribute__((section(".modinfo"))) = +"depends="; + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/tffs-pm26.c linux-2.6.30.4/drivers/block/tffs/tffs-pm26.c --- linux-2.6.30.4-orig/drivers/block/tffs/tffs-pm26.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/tffs-pm26.c 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,184 @@ +/****************************************************************************** + * * + * Project: DOC Driver for Linux 2.6 Block device driver for mDOC H3 family * + * of devices under Linux kernel 2.6. * + * * + * Version: 1.0 * + * Email questions to: oemsupport@sandisk.com * + * Copyright (C) SanDisk IL Ltd. 1995 - 2007 * + * SanDisk IL Ltd., 7 Atir Yeda Street, Kfar Saba 44425, Israel * + * * + ****************************************************************************** + * * + * 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 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, which is set forth in the readme.txt file. * + * 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., 51 * + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + * * + * This License does not grant you any right to use the trademarks, service * + * marks or logos of SanDisk IL Ltd. or SanDisk Corporation. * + * Subject to the foregoing, SanDisk IL Ltd., for itself and on behalf of its * + * licensors, hereby reserves all intellectual property rights in the program,* + * except for the rights expressly granted in this License. * + * * + ******************************************************************************/ + +/* + * $Log$ + */ + + + +#include "tffsdrv.h" + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) && defined(CONFIG_PM) + +# if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) + + /****************************************************************************** + * * + * Generic power management implementation for Linux kernels 2.6.15 and up. * + * * + ******************************************************************************/ + + static int suspend_driver (struct platform_device * dev, pm_message_t state) + { + tffs_suspend(); + return 0; + } + + static int resume_driver (struct platform_device * dev) + { + tffs_resume (); + return 0; + } + + static struct platform_driver pm_driver = + { + .suspend = suspend_driver, + .resume = resume_driver, + .driver = + { + .name = TFFS_DEVICE_NAME, + }, + }; + + int tffs_pm_init (void) + { + int rc; + + if( (rc = platform_driver_register(&pm_driver)) != 0) + PrintkError ("platform_driver_register() failed, PM disabled"); + return rc; + } + + int tffs_pm_exit (void) + { + platform_driver_unregister (&pm_driver); + return 0; + } + +# else /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)) */ + + /****************************************************************************** + * * + * Generic power management implementation for Linux kernels 2.6.0 .. 2.6.14 * + * * + ******************************************************************************/ + +# if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,11)) + static int suspend_driver (struct device * dev, pm_message_t state, u32 level) +# else + static int suspend_driver (struct device * dev, u32 state, u32 level) +# endif + { + switch (level) + { + case SUSPEND_POWER_DOWN: + tffs_suspend (); + break; + + case SUSPEND_DISABLE: + case SUSPEND_SAVE_STATE: + default: + break; + } + return 0; + } + + static int resume_driver (struct device * dev, u32 level) + { + switch (level) + { + case RESUME_POWER_ON: + tffs_resume (); + break; + + case RESUME_RESTORE_STATE: + case RESUME_ENABLE: + default: + break; + } + return 0; + } + + static + void pm_release_device (struct device * pdev) + { } + + static struct platform_device pm_device = { + .name = TFFS_DEVICE_NAME, + .id = 0, + .dev.release = pm_release_device, + }; + + static struct device_driver pm_driver = { + .name = TFFS_DEVICE_NAME, + .bus = &platform_bus_type, + .suspend = suspend_driver, + .resume = resume_driver, + }; + + int tffs_pm_init (void) + { + /* register device with Linux Device Manager */ + if( platform_device_register(&pm_device) != 0 ) + { + PrintkError ("can't register device %s with LDM", pm_device.name); + return -ENODEV; + } + + /* register driver with Linux Device Manager */ + if( driver_register(&pm_driver) != 0 ) + { + PrintkError ("can't register driver %s with LDM", pm_driver.name); + + /* unregister device from Linux Device Manager */ + platform_device_unregister (&pm_device); + + return -ENODEV; + } + + return 0; /* success */ + } + + int tffs_pm_exit (void) + { + /* unregister driver from Linux Device Manager */ + driver_unregister (&pm_driver); + + /* unregister device from Linux Device Manager */ + platform_device_unregister (&pm_device); + + return 0; + } + +# endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)) */ +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) && defined(CONFIG_PM) */ + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/trace32.c linux-2.6.30.4/drivers/block/tffs/trace32.c --- linux-2.6.30.4-orig/drivers/block/tffs/trace32.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/trace32.c 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,48 @@ +/****************************************************************************** + * * + * Project: DOC Driver for Linux 2.6 Block device driver for mDOC H3 family * + * of devices under Linux kernel 2.6. * + * * + * Version: 1.0 * + * Email questions to: oemsupport@sandisk.com * + * Copyright (C) SanDisk IL Ltd. 1995 - 2007 * + * SanDisk IL Ltd., 7 Atir Yeda Street, Kfar Saba 44425, Israel * + * * + ****************************************************************************** + * * + * 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 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, which is set forth in the readme.txt file. * + * 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., 51 * + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + * * + * This License does not grant you any right to use the trademarks, service * + * marks or logos of SanDisk IL Ltd. or SanDisk Corporation. * + * Subject to the foregoing, SanDisk IL Ltd., for itself and on behalf of its * + * licensors, hereby reserves all intellectual property rights in the program,* + * except for the rights expressly granted in this License. * + * * + ******************************************************************************/ + +/* + * $Log$ + */ + + +#include +#include +#include + +/* + * These variables reside at the beginning of respective sections +*/ +int trace32_data = 0x11223344; /* beginning of .data section */ +int trace32_bss; /* beginning of .bss section */ +const int trace32_rodata = 0x55667788; /* beginning of .rodata section */ + + diff -urN linux-2.6.30.4-orig/drivers/block/tffs/VERSIONS.TXT linux-2.6.30.4/drivers/block/tffs/VERSIONS.TXT --- linux-2.6.30.4-orig/drivers/block/tffs/VERSIONS.TXT 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/block/tffs/VERSIONS.TXT 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,205 @@ + + ******************************************************************************* + * * + * DOC Driver for Linux 2.6 * + * Source Code Edition * + * * + * VERSIONS * + * * + * * + * Version 1.0.86-RTM, released on April 27 2008 * + * Based on DOC Driver Block Device SDK version 1.1.0 RTM * + * * + * Email questions to: oemsupport@sandisk.com * + * Copyright (C) SanDisk IL Ltd. 1995 - 2008 * + * SanDisk IL Ltd., 7 Atir Yeda Street, Kfar Saba 44425, Israel * + * * + * Please note that effective January 1, 2007, the name msystems Ltd. was * + * changed to SanDisk IL Ltd. * + * * + ******************************************************************************* + * * + * 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 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, which is set forth in the readme.txt file. * + * 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., 51 * + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + * * + * This License does not grant you any right to use the trademarks, service * + * marks or logos of SanDisk IL Ltd. or SanDisk Corporation. * + * Subject to the foregoing, SanDisk IL Ltd., for itself and on behalf of its * + * licensors, hereby reserves all intellectual property rights in the program, * + * except for the rights expressly granted in this License. * + * * + ******************************************************************************* + +This package is release version for DOC driver for mDOC H3. + +The list below documents and logs the changes in DOC driver for Linux +over time. + +Version 1.0.86-RTM - April 27, 2008 +---------------------------------------- +1. DOC Driver SDK changes. +1.1. Bug Fixes + - Mount Timeout was changed + + +Version 1.0.85-beta - December 27, 2007 +---------------------------------------- +1. DOC Driver SDK changes. +1.1. Bug Fixes + - assorted bug fixes for cascaded configuration + + +Version 1.0.84-alpha - November 16, 2007 +---------------------------------------- +1. Linux driver changes. +1.1. Added "tffs_unformat= command line option for unformatting mDOC device +1.2. New cylinder/head/sectors-per-track geometry calculation for mDOC capacities + of 4 GByte and higher. +1.3. Improved locking in tffsdrv26.c. + + +Version 1.0.83 - January 07, 2007 +--------------------------------- +1. Supports the following mDOC Products: + - mDOC H3 family + +2. DOC Driver SDK changes. +2.1. Bug Fixes + - Fixed various compilation warnings. + - Added wait for ATA BUSY de assertion before performing ATA reset during init. + - Fixed IRQ handling in case of cascaded configuration. + - Fixed OTW for cascaded configuration. + - Enable removing 'lock enabled' attribute from a partition. + - Added SDK level secure-wipe power-failure immunity. +2.2. Added mDOC H3 2GBit device simulation. + +3. Linux driver changes. +3.1. Added support for Intel PXA27x board (aka "Mainstone"). +3.2. The following bugs has been fixed in this version: + - The FL_IOCTL_GET_INFO Advanced Function causes CPU fault on 13-th and + higher disks. + - The FL_IOCTL_IPL_HW_PROTECTION Advanced Function fails. + - Write performance is low in case of cascaded mDOC H3 configuration. +3.3. The following files have been changed: + - tffsdrv26.c + - tffsarch.c + - tffs-pm26.c + - flcustom.c + - flsystem.c + - flcustom.h + - flsystem.h + - tffsdrv.h + + +Version 1.0.82-beta - November 13, 2006 +--------------------------------------- +1. Supports the following mDOC Products: + - mDOC H3 family + +2. DOC Driver SDK changes. +2.1. Bug Fixes: + - Cascaded configuration support. + - DMA handling when data size exceeds frame size. + - OTW setting changed when changing protection type. + - SLOCK setting disabled when using flChangeProtectionType. + - flChangeProtectionKey() returned flWrongKey instead of flHWProtection upon failure. + - Set IPL partition as 'protectable' upon creation. +2.2. API Changes: + - IPL protection APIs added. + - 16 partitions supported (14 user partitions + mandatory IPL and OTP partitions). + - TL_LEAVE_SOME_PARTITIONS added to flFlashFormat() + - RW protection enabled. +2.3. Joint Protection removed. +2.4. Compilation warnings fixed. + +3. Linux driver changes. +3.1. Added mDOC IRQ support for Texas Instruments OMAP2420 ("H4") board. +3.2. Added s/w DMA support for Texas Instruments OMAP2420 ("H4") board. +3.3. Added suspend/resume support for Texas Instruments OMAP2420 ("H4") board. +3.4. Added "tffs_dpd_timeout=" command line option for better automatic + power-down control. +3.5. Added "tffs_memcpy=1" command line option to improve performance. +3.6. Number of supported "disks" (BDTL partitions) has been increased from + 6 to 12. + + + +Version 1.0.81-alpha - August 10, 2006 +-------------------------------------- +1. Supports the following mDOC Products: + - mDOC H3 family + + + +Disclaimer of Liability +----------------------- + +SanDisk IL Ltd.'s general policy does not recommend the use of its products +in life support applications wherein a failure or malfunction of the +product may directly threaten life or injury. +Accordingly, in any use of products in life support systems or other +applications where failure could cause damage, injury or loss of life, +the products should only be incorporated in systems designed with +appropriate redundancy, fault tolerant or back-up features. + +SanDisk IL shall not be liable for any loss, injury or damage caused by +use of the Products in any of the following applications: + +Special applications such as military related equipment, nuclear reactor +control, and aerospace + +Control devices for automotive vehicles, train, ship and traffic +equipment + +Safety system for disaster prevention and crime prevention + +Medical-related equipment including medical measurement device. + + + +Contact information +------------------- + +For comments, questions and bug reports, please contact your SanDisk +representative or e-mail us at oemsupport@sandisk.com. + + This document is for information use only and is subject to change + without prior notice. + + SanDisk IL Ltd. assumes no responsibility for any errors that may + appear in this document, nor for incidental or consequential damages + resulting from the furnishing, performance or use of this material. + + SanDisk IL's products are not warranted to operate without failure. + SanDisk IL's general policy does not recommend the use of its products + in life support applications where a failure or malfunction of the + product could cause injury or loss of life. Per SanDisk IL's Terms and + Conditions of Sale, the user of SanDisk IL's products in life support + applications assumes all risk of such use and indemnifies SanDisk IL + against all damages. See "Disclaimer of Liability". Accordingly, in + any use of the Product in life support systems or other applications + where failure could cause injury or loss of life, the Product should + only be incorporated in systems designed with appropriate and + sufficient redundancy or backup features. + + All parts of the SanDisk IL's documentation are protected by copyright + law and all rights reserved. + + Contact your local SanDisk sales office or distributor to obtain the + latest specifications before placing your order. + + (C) 1995-2007 SanDisk IL Ltd. All rights reserved. + + mDOC, DOC, TrueFFS, SureFS, SanDisk and SanDisk logo are registered + trademarks of SanDisk IL Ltd. and SanDisk Corporation, respectively. + Other product names or service marks mentioned herein may be trademarks + or registered trademarks of their respective owners and are hereby + acknowledged. diff -urN linux-2.6.30.4-orig/drivers/usb/gadget/pxa27x_udc.c linux-2.6.30.4/drivers/usb/gadget/pxa27x_udc.c --- linux-2.6.30.4-orig/drivers/usb/gadget/pxa27x_udc.c 2009-07-31 00:34:47.000000000 +0200 +++ linux-2.6.30.4/drivers/usb/gadget/pxa27x_udc.c 2009-08-12 10:18:55.000000000 +0200 @@ -1481,8 +1481,10 @@ if (gpio_is_valid(udc->mach->gpio_pullup)) gpio_set_value(udc->mach->gpio_pullup, !udc->mach->gpio_pullup_inverted); - if (udc->mach->udc_command) + + if (udc->mach->udc_command) { udc->mach->udc_command(PXA2XX_UDC_CMD_CONNECT); + } } else { if (gpio_is_valid(udc->mach->gpio_pullup)) gpio_set_value(udc->mach->gpio_pullup, @@ -1767,6 +1769,8 @@ struct pxa_udc *udc = the_controller; int retval; +// printk("Marco %s, testpoint\n", __FUNCTION__); + if (!driver || driver->speed < USB_SPEED_FULL || !driver->bind || !driver->disconnect || !driver->setup) return -EINVAL; @@ -1775,10 +1779,12 @@ if (udc->driver) return -EBUSY; + dplus_pullup(udc, 0); + /* first hook up the driver ... */ udc->driver = driver; udc->gadget.dev.driver = &driver->driver; - dplus_pullup(udc, 1); + retval = device_add(&udc->gadget.dev); if (retval) { @@ -1802,6 +1808,8 @@ } } + dplus_pullup(udc, 1); + if (should_enable_udc(udc)) udc_enable(udc); return 0; @@ -1814,6 +1822,8 @@ add_fail: udc->driver = NULL; udc->gadget.dev.driver = NULL; + +// printk("Marco %s, testpoint, something is shit.\n", __FUNCTION__); return retval; } EXPORT_SYMBOL(usb_gadget_register_driver); @@ -2299,6 +2309,9 @@ u32 udccr = udc_readl(udc, UDCCR); u32 udcisr1_spec; +// printk("Marco %s, testpoint.\n", __FUNCTION__); +// printk("Interrupt, UDCISR0:0x%08x, UDCISR1:0x%08x, UDCCR:0x%08x\n", udcisr0, udcisr1, udccr); + dev_vdbg(udc->dev, "Interrupt, UDCISR0:0x%08x, UDCISR1:0x%08x, " "UDCCR:0x%08x\n", udcisr0, udcisr1, udccr); @@ -2385,17 +2398,24 @@ if (udc->irq < 0) return udc->irq; +// printk("Marco %s, irq = %d\n", __FUNCTION__, udc->irq); + udc->dev = &pdev->dev; udc->mach = pdev->dev.platform_data; udc->transceiver = otg_get_transceiver(); gpio = udc->mach->gpio_pullup; +// printk("Marco %s, pullupgpio = %d\n", __FUNCTION__, gpio = udc->mach->gpio_pullup); + if (gpio_is_valid(gpio)) { retval = gpio_request(gpio, "USB D+ pullup"); if (retval == 0) gpio_direction_output(gpio, udc->mach->gpio_pullup_inverted); } + else + printk("Marco %s, gpio not valid\n", __FUNCTION__); + if (retval) { dev_err(&pdev->dev, "Couldn't request gpio %d : %d\n", gpio, retval); @@ -2454,6 +2474,8 @@ struct pxa_udc *udc = platform_get_drvdata(_dev); int gpio = udc->mach->gpio_pullup; + printk("Marco %s, testpoint.\n", __FUNCTION__); + usb_gadget_unregister_driver(udc->driver); free_irq(udc->irq, udc); pxa_cleanup_debugfs(udc); @@ -2475,6 +2497,8 @@ { struct pxa_udc *udc = platform_get_drvdata(_dev); + printk("Marco %s, testpoint.\n", __FUNCTION__); + if (udc_readl(udc, UDCCR) & UDCCR_UDE) udc_disable(udc); } diff -urN linux-2.6.30.4-orig/drivers/usb/gadget/pxa27x_udc_sysgo.c linux-2.6.30.4/drivers/usb/gadget/pxa27x_udc_sysgo.c --- linux-2.6.30.4-orig/drivers/usb/gadget/pxa27x_udc_sysgo.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/usb/gadget/pxa27x_udc_sysgo.c 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,2428 @@ +/* + * Handles the Intel 27x USB Device Controller (UDC) + * + * Copyright (C) 2002 Intrinsyc, Inc. (Frank Becker) + * Copyright (C) 2003 Robert Schwebel, Pengutronix + * Copyright (C) 2003 Benedikt Spranger, Pengutronix + * Copyright (C) 2003 David Brownell + * Copyright (C) 2003 Joshua Wise + * Copyright (C) 2004 Intel Corporation + * Copyright (C) 2005 SDG Systems, LLC (Aric Blumer) + * Copyright (C) 2005-2006 Openedhand Ltd. (Richard Purdie) + * + * 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 + * + */ + +#undef DEBUG +//#define DEBUG 1 +//#define VERBOSE DBG_VERBOSE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +//#include +#include + +#ifdef CONFIG_ARCH_PXA +//#include +#include /* FIXME: for PSSR */ +#endif + +#include +//#include +#include + +#include + + +/* + * This driver handles the USB Device Controller (UDC) in Intel's PXA 27x + * series processors. + * + * Such controller drivers work with a gadget driver. The gadget driver + * returns descriptors, implements configuration and data protocols used + * by the host to interact with this device, and allocates endpoints to + * the different protocol interfaces. The controller driver virtualizes + * usb hardware so that the gadget drivers will be more portable. + * + * This UDC hardware wants to implement a bit too much USB protocol. The + * biggest issue is that the endpoints have to be setup before the controller + * can be enabled and each endpoint can only have one configuration, interface + * and alternative interface number. Once enabled, these cannot be changed + * without a controller reset. + * + * Intel Errata #22 mentions issues when changing alternate interface. + * The exact meaning of this remains uncertain as gadget drivers using alternate + * interfaces such as CDC-Ethernet appear to work... + */ + +#define DRIVER_VERSION "01-01-2006" +#define DRIVER_DESC "PXA 27x USB Device Controller driver" + +static const char driver_name [] = "pxa27x_udc"; + +static const char ep0name [] = "ep0"; + + +//#define USE_DMA +#undef USE_DMA + +#ifdef CONFIG_PROC_FS +#define UDC_PROC_FILE +#endif + +#include "pxa27x_udc_sysgo.h" + +#ifdef USE_DMA +static int use_dma = 1; +module_param(use_dma, bool, 0); +MODULE_PARM_DESC(use_dma, "true to use dma"); + +static void dma_nodesc_handler(int dmach, void *_ep); +static void kick_dma(struct pxa27x_ep *ep, struct pxa27x_request *req); + +#define DMASTR " (dma support)" + +#else /* !USE_DMA */ +#define DMASTR " (pio only)" +#endif + +#define UDCISR0_IR0 0x3 +#define UDCISR_INT_MASK (UDC_INT_FIFOERROR | UDC_INT_PACKETCMP) +#define UDCICR_INT_MASK UDCISR_INT_MASK + +#define UDCCSR_MASK (UDCCSR_FST | UDCCSR_DME) + +static void pxa27x_ep_fifo_flush(struct usb_ep *ep); +static void nuke(struct pxa27x_ep *, int status); +static void udc_init_ep(struct pxa27x_udc *dev); + +/* one GPIO should be used to detect VBUS from the host */ +/* + * Endpoint Functions + */ +static void pio_irq_enable(int ep_num) +{ + if (ep_num < 16) + UDCICR0 |= 3 << (ep_num * 2); + else { + ep_num -= 16; + UDCICR1 |= 3 << (ep_num * 2); + } +} + +static void pio_irq_disable(int ep_num) +{ + ep_num &= 0xf; + if (ep_num < 16) + UDCICR0 &= ~(3 << (ep_num * 2)); + else { + ep_num -= 16; + UDCICR1 &= ~(3 << (ep_num * 2)); + } +} + +/* The UDCCR reg contains mask and interrupt status bits, + * so using '|=' isn't safe as it may ack an interrupt. + */ +#define UDCCR_MASK_BITS (UDCCR_OEN | UDCCR_UDE) + +static inline void udc_set_mask_UDCCR(int mask) +{ + UDCCR = (UDCCR & UDCCR_MASK_BITS) | (mask & UDCCR_MASK_BITS); +} + +static inline void udc_clear_mask_UDCCR(int mask) +{ + UDCCR = (UDCCR & UDCCR_MASK_BITS) & ~(mask & UDCCR_MASK_BITS); +} + +static inline void udc_ack_int_UDCCR(int mask) +{ + /* udccr contains the bits we dont want to change */ + __u32 udccr = UDCCR & UDCCR_MASK_BITS; + + UDCCR = udccr | (mask & ~UDCCR_MASK_BITS); +} + +/* + * Endpoint enable/disable + * + * Not much to do here as the ep_alloc function sets up most things. Once + * enabled, not much of the pxa27x configuration can be changed. + * + */ +static int pxa27x_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) +{ + struct pxa27x_virt_ep *virt_ep = container_of(_ep, struct pxa27x_virt_ep, usb_ep); + struct pxa27x_ep *ep = virt_ep->pxa_ep; + struct pxa27x_udc *dev; + + if (!_ep || !desc || _ep->name == ep0name + || desc->bDescriptorType != USB_DT_ENDPOINT + || ep->fifo_size < le16_to_cpu(desc->wMaxPacketSize)) { + dev_err(ep->dev->dev, "%s, bad ep or descriptor\n", __FUNCTION__); + return -EINVAL; + } + + /* xfer types must match, except that interrupt ~= bulk */ + if( ep->ep_type != USB_ENDPOINT_XFER_BULK + && desc->bmAttributes != USB_ENDPOINT_XFER_INT) { + dev_err(ep->dev->dev, "%s, %s type mismatch\n", __FUNCTION__, _ep->name); + return -EINVAL; + } + + /* hardware _could_ do smaller, but driver doesn't */ + if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK + && le16_to_cpu (desc->wMaxPacketSize) + != BULK_FIFO_SIZE) + || !desc->wMaxPacketSize) { + dev_err(ep->dev->dev, "%s, bad %s maxpacket\n", __FUNCTION__, _ep->name); + return -ERANGE; + } + + dev = ep->dev; + if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) { + dev_err(ep->dev->dev, "%s, bogus device state\n", __FUNCTION__); + return -ESHUTDOWN; + } + + ep->desc = desc; + ep->dma = -1; + ep->stopped = 0; + ep->pio_irqs = ep->dma_irqs = 0; + ep->usb_ep->maxpacket = le16_to_cpu(desc->wMaxPacketSize); + + /* flush fifo (mostly for OUT buffers) */ + pxa27x_ep_fifo_flush(_ep); + + /* ... reset halt state too, if we could ... */ + +#ifdef USE_DMA + /* for (some) bulk and ISO endpoints, try to get a DMA channel and + * bind it to the endpoint. otherwise use PIO. + */ + dev_dbg(ep->dev->dev, "%s: called attributes=%d\n", __FUNCTION__, ep->ep_type); + switch (ep->ep_type) { + case USB_ENDPOINT_XFER_ISOC: + if (le16_to_cpu(desc->wMaxPacketSize) % 32) + break; + // fall through + case USB_ENDPOINT_XFER_BULK: + if (!use_dma || !ep->reg_drcmr) + break; + ep->dma = pxa_request_dma((char *)_ep->name, (le16_to_cpu(desc->wMaxPacketSize) > 64) + ? DMA_PRIO_MEDIUM : DMA_PRIO_LOW, dma_nodesc_handler, ep); + if (ep->dma >= 0) { + *ep->reg_drcmr = DRCMR_MAPVLD | ep->dma; + dev_dbg(ep->dev->dev, "%s using dma%d\n", _ep->name, ep->dma); + } + default: + break; + } +#endif + DBG(DBG_VERBOSE, "enabled %s\n", _ep->name); + return 0; +} + +static int pxa27x_ep_disable(struct usb_ep *_ep) +{ + struct pxa27x_virt_ep *virt_ep = container_of(_ep, struct pxa27x_virt_ep, usb_ep); + struct pxa27x_ep *ep = virt_ep->pxa_ep; + unsigned long flags; + + if (!_ep || !ep->desc) { + dev_err(ep->dev->dev, "%s, %s not enabled\n", __FUNCTION__, + _ep ? _ep->name : NULL); + return -EINVAL; + } + local_irq_save(flags); + nuke(ep, -ESHUTDOWN); + +#ifdef USE_DMA + if (ep->dma >= 0) { + *ep->reg_drcmr = 0; + pxa_free_dma(ep->dma); + ep->dma = -1; + } +#endif + + /* flush fifo (mostly for IN buffers) */ + pxa27x_ep_fifo_flush(_ep); + + ep->desc = 0; + ep->stopped = 1; + + local_irq_restore(flags); + DBG(DBG_VERBOSE, "%s disabled\n", _ep->name); + return 0; +} + + + +/* for the pxa27x, these can just wrap kmalloc/kfree. gadget drivers + * must still pass correctly initialized endpoints, since other controller + * drivers may care about how it's currently set up (dma issues etc). + */ + +/* + * pxa27x_ep_alloc_request - allocate a request data structure + */ +static struct usb_request * +pxa27x_ep_alloc_request(struct usb_ep *_ep, unsigned gfp_flags) +{ + struct pxa27x_request *req; + + req = kzalloc(sizeof(*req), gfp_flags); + if (!req) + return 0; + + INIT_LIST_HEAD(&req->queue); + return &req->req; +} + + +/* + * pxa27x_ep_free_request - deallocate a request data structure + */ +static void +pxa27x_ep_free_request(struct usb_ep *_ep, struct usb_request *_req) +{ + struct pxa27x_request *req; + + req = container_of(_req, struct pxa27x_request, req); + WARN_ON(!list_empty(&req->queue)); + kfree(req); +} + + +/* PXA cache needs flushing with DMA I/O (it's dma-incoherent), but there's + * no device-affinity and the heap works perfectly well for i/o buffers. + * It wastes much less memory than dma_alloc_coherent() would, and even + * prevents cacheline (32 bytes wide) sharing problems. + */ +static void * +pxa27x_ep_alloc_buffer(struct usb_ep *_ep, unsigned bytes, dma_addr_t *dma, unsigned gfp_flags) +{ + char *retval; + + retval = kmalloc(bytes, gfp_flags & ~(__GFP_DMA|__GFP_HIGHMEM)); + if (retval) + *dma = virt_to_bus(retval); + return retval; +} + +static void +pxa27x_ep_free_buffer(struct usb_ep *_ep, void *buf, dma_addr_t dma, unsigned bytes) +{ + kfree(buf); +} + +/*-------------------------------------------------------------------------*/ + +/* + * done - retire a request; caller blocked irqs + */ +static void done(struct pxa27x_ep *ep, struct pxa27x_request *req, int status) +{ + list_del_init(&req->queue); + if (likely (req->req.status == -EINPROGRESS)) + req->req.status = status; + else + status = req->req.status; + + if (status && status != -ESHUTDOWN) + DBG(DBG_VERBOSE, "complete %s req %p stat %d len %u/%u\n", + ep->usb_ep->name, &req->req, status, + req->req.actual, req->req.length); + + /* don't modify queue heads during completion callback */ + req->req.complete(ep->usb_ep, &req->req); +} + + +static inline void ep0_idle(struct pxa27x_udc *dev) +{ + dev->ep0state = EP0_IDLE; +} + +static int write_packet(volatile u32 *uddr, struct pxa27x_request *req, unsigned max) +{ + u32 *buf; + int length, count, remain; + + buf = (u32*)(req->req.buf + req->req.actual); + prefetch(buf); + + /* how big will this packet be? */ + length = min(req->req.length - req->req.actual, max); + req->req.actual += length; + + remain = length & 0x3; + count = length & ~(0x3); + + //dev_dbg(ep->dev->dev, "Length %d, Remain %d, Count %d\n",length, remain, count); + + while (likely(count)) { + //dev_dbg(ep->dev->dev, "Sending:0x%x\n", *buf); + *uddr = *buf++; + count -= 4; + } + + if (remain) { + volatile u8* reg=(u8*)uddr; + char *rd =(u8*)buf; + + while (remain--) { + *reg=*rd++; + } + } + + return length; +} + +/* + * write to an IN endpoint fifo, as many packets as possible. + * irqs will use this to write the rest later. + * caller guarantees at least one packet buffer is ready (or a zlp). + */ +static int +write_fifo(struct pxa27x_ep *ep, struct pxa27x_request *req) +{ + unsigned max; + + max = le16_to_cpu(ep->desc->wMaxPacketSize); + do { + int count, is_last, is_short; + + //dev_dbg(ep->dev->dev, "write_fifo7 %x\n", *ep->reg_udccsr); + + if (*ep->reg_udccsr & UDCCSR_PC) { + //dev_dbg(ep->dev->dev, "Transmit Complete\n"); + *ep->reg_udccsr = UDCCSR_PC | (*ep->reg_udccsr & UDCCSR_MASK); + } + + if (*ep->reg_udccsr & UDCCSR_TRN) { + //dev_dbg(ep->dev->dev, "Clearing Underrun\n"); + *ep->reg_udccsr = UDCCSR_TRN | (*ep->reg_udccsr & UDCCSR_MASK); + } + //dev_dbg(ep->dev->dev, "write_fifo8 %x\n", *ep->reg_udccsr); + + count = write_packet(ep->reg_udcdr, req, max); + + /* last packet is usually short (or a zlp) */ + if (unlikely (count != max)) + is_last = is_short = 1; + else { + if (likely(req->req.length != req->req.actual) + || req->req.zero) + is_last = 0; + else + is_last = 1; + /* interrupt/iso maxpacket may not fill the fifo */ + is_short = unlikely (max < ep->fifo_size); + } + + //dev_dbg(ep->dev->dev, "write_fifo0 %x\n", *ep->reg_udccsr); + + dev_dbg(ep->dev->dev, "wrote %s count:%d bytes%s%s %d left %p\n", + ep->usb_ep->name, count, + is_last ? "/L" : "", is_short ? "/S" : "", + req->req.length - req->req.actual, &req->req); + + /* let loose that packet. maybe try writing another one, + * double buffering might work. + */ + + if (is_short) + *ep->reg_udccsr = UDCCSR_SP | (*ep->reg_udccsr & UDCCSR_MASK); + + dev_dbg(ep->dev->dev, "write_fifo0.5 %x\n", *ep->reg_udccsr); + + /* requests complete when all IN data is in the FIFO */ + if (is_last) { + done(ep, req, 0); + if (list_empty(&ep->queue) || unlikely(ep->dma >= 0)) { + pio_irq_disable(ep->pxa_ep_num); + //dev_dbg(ep->dev->dev, "write_fifo1 %x\n", *ep->reg_udccsr); +#ifdef USE_DMA + /* unaligned data and zlps couldn't use dma */ + if (unlikely(!list_empty(&ep->queue))) { + req = list_entry(ep->queue.next, + struct pxa27x_request, queue); + kick_dma(ep,req); + return 0; + } +#endif + } + //dev_dbg(ep->dev->dev, "write_fifo2 %x\n", *ep->reg_udccsr); + return 1; + } + + // TODO experiment: how robust can fifo mode tweaking be? + // double buffering is off in the default fifo mode, which + // prevents TFS from being set here. + + } while (*ep->reg_udccsr & UDCCSR_FS); + //dev_dbg(ep->dev->dev, "write_fifo2 %x\n", *ep->reg_udccsr); + return 0; +} + +/* caller asserts req->pending (ep0 irq status nyet cleared); starts + * ep0 data stage. these chips want very simple state transitions. + */ +static inline +void ep0start(struct pxa27x_udc *dev, u32 flags, const char *tag) +{ + UDCCSR0 = flags|UDCCSR0_SA|UDCCSR0_OPC; + UDCISR0 = UDCICR_INT(0, UDC_INT_FIFOERROR | UDC_INT_PACKETCMP); + dev->req_pending = 0; + DBG(DBG_VERY_NOISY, "%s %s, %02x/%02x\n", + __FUNCTION__, tag, UDCCSR0, flags); +} + +static int +write_ep0_fifo(struct pxa27x_ep *ep, struct pxa27x_request *req) +{ + unsigned count; + int is_short; + + count = write_packet(&UDCDR0, req, EP0_FIFO_SIZE); + ep->dev->stats.write.bytes += count; + + /* last packet "must be" short (or a zlp) */ + is_short = (count != EP0_FIFO_SIZE); + + DBG(DBG_VERY_NOISY, "ep0in %d bytes %d left %p\n", count, + req->req.length - req->req.actual, &req->req); + + if (unlikely (is_short)) { + if (ep->dev->req_pending) + ep0start(ep->dev, UDCCSR0_IPR, "short IN"); + else + UDCCSR0 = UDCCSR0_IPR; + + count = req->req.length; + done(ep, req, 0); + ep0_idle(ep->dev); +#ifndef CONFIG_ARCH_IXP4XX +#if 0 + /* This seems to get rid of lost status irqs in some cases: + * host responds quickly, or next request involves config + * change automagic, or should have been hidden, or ... + * + * FIXME get rid of all udelays possible... + */ + if (count >= EP0_FIFO_SIZE) { + count = 100; + do { + if ((UDCCSR0 & UDCCSR0_OPC) != 0) { + /* clear OPC, generate ack */ + UDCCSR0 = UDCCSR0_OPC; + break; + } + count--; + udelay(1); + } while (count); + } +#endif +#endif + } else if (ep->dev->req_pending) + ep0start(ep->dev, 0, "IN"); + return is_short; +} + + +/* + * read_fifo - unload packet(s) from the fifo we use for usb OUT + * transfers and put them into the request. caller should have made + * sure there's at least one packet ready. + * + * returns true if the request completed because of short packet or the + * request buffer having filled (and maybe overran till end-of-packet). + */ +static int read_fifo(struct pxa27x_ep *ep, struct pxa27x_request *req) +{ + for (;;) { + u32 *buf; + int bufferspace, count, is_short; + + /* make sure there's a packet in the FIFO.*/ + if (unlikely ((*ep->reg_udccsr & UDCCSR_PC) == 0)) + break; + buf =(u32*) (req->req.buf + req->req.actual); + prefetchw(buf); + bufferspace = req->req.length - req->req.actual; + + /* read all bytes from this packet */ + if (likely (*ep->reg_udccsr & UDCCSR_BNE)) { + count = 0x3ff & *ep->reg_udcbcr; + req->req.actual += min(count, bufferspace); + } else /* zlp */ + count = 0; + + is_short = (count < ep->usb_ep->maxpacket); + dev_dbg(ep->dev->dev, "read %s udccsr:%02x, count:%d bytes%s req %p %d/%d\n", + ep->usb_ep->name, *ep->reg_udccsr, count, + is_short ? "/S" : "", + &req->req, req->req.actual, req->req.length); + + count = min(count, bufferspace); + while (likely (count > 0)) { + *buf++ = *ep->reg_udcdr; + count -= 4; + } + dev_dbg(ep->dev->dev, "Buf:0x%p\n", req->req.buf); + + *ep->reg_udccsr = UDCCSR_PC; + /* RPC/RSP/RNE could now reflect the other packet buffer */ + + /* completion */ + if (is_short || req->req.actual == req->req.length) { + done(ep, req, 0); + if (list_empty(&ep->queue)) + pio_irq_disable(ep->pxa_ep_num); + return 1; + } + + /* finished that packet. the next one may be waiting... */ + } + return 0; +} + +/* + * special ep0 version of the above. no UBCR0 or double buffering; status + * handshaking is magic. most device protocols don't need control-OUT. + * CDC vendor commands (and RNDIS), mass storage CB/CBI, and some other + * protocols do use them. + */ +static int read_ep0_fifo(struct pxa27x_ep *ep, struct pxa27x_request *req) +{ + u32 *buf, word; + unsigned bufferspace; + + buf = (u32*) (req->req.buf + req->req.actual); + bufferspace = req->req.length - req->req.actual; + + while (UDCCSR0 & UDCCSR0_RNE) { + word = UDCDR0; + + if (unlikely (bufferspace == 0)) { + /* this happens when the driver's buffer + * is smaller than what the host sent. + * discard the extra data. + */ + if (req->req.status != -EOVERFLOW) + dev_info(ep->dev->dev, "%s overflow\n", ep->usb_ep->name); + req->req.status = -EOVERFLOW; + } else { + *buf++ = word; + req->req.actual += 4; + bufferspace -= 4; + } + } + + UDCCSR0 = UDCCSR0_OPC ; + + /* completion */ + if (req->req.actual >= req->req.length) + return 1; + + /* finished that packet. the next one may be waiting... */ + return 0; +} + +#ifdef USE_DMA + +#define MAX_IN_DMA ((DCMD_LENGTH + 1) - BULK_FIFO_SIZE) +static void kick_dma(struct pxa27x_ep *ep, struct pxa27x_request *req) +{ + u32 dcmd = 0; + u32 len = req->req.length; + u32 buf = req->req.dma; + u32 fifo = io_v2p((u32)ep->reg_udcdr); + + buf += req->req.actual; + len -= req->req.actual; + ep->dma_con = 0; + + DMSG("%s: req:0x%p length:%d, actual:%d dma:%d\n", + __FUNCTION__, &req->req, req->req.length, + req->req.actual,ep->dma); + + /* no-descriptor mode can be simple for bulk-in, iso-in, iso-out */ + DCSR(ep->dma) = DCSR_NODESC; + if (buf & 0x3) + DALGN |= 1 << ep->dma; + else + DALGN &= ~(1 << ep->dma); + + if (ep->dir_in) { + DSADR(ep->dma) = buf; + DTADR(ep->dma) = fifo; + if (len > MAX_IN_DMA) { + len= MAX_IN_DMA; + ep->dma_con =1 ; + } else if (len >= ep->usb_ep->maxpacket) { + if ((ep->dma_con = (len % ep->usb_ep->maxpacket) != 0)) + len = ep->usb_ep->maxpacket; + } + dcmd = len | DCMD_BURST32 | DCMD_WIDTH4 | DCMD_ENDIRQEN + | DCMD_FLOWTRG | DCMD_INCSRCADDR; + } else { + DSADR(ep->dma) = fifo; + DTADR(ep->dma) = buf; + dcmd = len | DCMD_BURST32 | DCMD_WIDTH4 | DCMD_ENDIRQEN + | DCMD_FLOWSRC | DCMD_INCTRGADDR; + } + *ep->reg_udccsr = UDCCSR_DME; + DCMD(ep->dma) = dcmd; + DCSR(ep->dma) = DCSR_NODESC | DCSR_EORIRQEN \ + | ((ep->dir_in) ? DCSR_STOPIRQEN : 0); + *ep->reg_drcmr = ep->dma | DRCMR_MAPVLD; + DCSR(ep->dma) |= DCSR_RUN; +} + +static void cancel_dma(struct pxa27x_ep *ep) +{ + struct pxa27x_request *req; + u32 tmp; + + if (DCSR(ep->dma) == 0 || list_empty(&ep->queue)) + return; + + DMSG("hehe dma:%d,dcsr:0x%x\n", ep->dma, DCSR(ep->dma)); + DCSR(ep->dma) = 0; + while ((DCSR(ep->dma) & DCSR_STOPSTATE) == 0) + cpu_relax(); + + req = list_entry(ep->queue.next, struct pxa27x_request, queue); + tmp = DCMD(ep->dma) & DCMD_LENGTH; + req->req.actual = req->req.length - tmp; + + /* the last tx packet may be incomplete, so flush the fifo. + * FIXME correct req.actual if we can + */ + *ep->reg_udccsr = UDCCSR_FEF; +} + +static void dma_nodesc_handler(int dmach, void *_ep) +{ + struct pxa27x_ep *ep = _ep; + struct pxa27x_request *req, *req_next; + u32 dcsr, tmp, completed; + + local_irq_disable(); + + req = list_entry(ep->queue.next, struct pxa27x_request, queue); + + DMSG("%s, buf:0x%p\n",__FUNCTION__, req->req.buf); + + ep->dma_irqs++; + ep->dev->stats.irqs++; + + completed = 0; + + dcsr = DCSR(dmach); + DCSR(ep->dma) &= ~DCSR_RUN; + + if (dcsr & DCSR_BUSERR) { + DCSR(dmach) = DCSR_BUSERR; + dev_err(ep->dev->dev, "DMA Bus Error\n"); + req->req.status = -EIO; + completed = 1; + } else if (dcsr & DCSR_ENDINTR) { + DCSR(dmach) = DCSR_ENDINTR; + if (ep->dir_in) { + tmp = req->req.length - req->req.actual; + /* Last packet is a short one*/ + if (tmp < ep->usb_ep->maxpacket) { + int count = 0; + + *ep->reg_udccsr = UDCCSR_SP | \ + (*ep->reg_udccsr & UDCCSR_MASK); + /*Wait for packet out */ + while( (count++ < 10000) && \ + !(*ep->reg_udccsr & UDCCSR_FS)); + if (count >= 10000) + DMSG("Failed to send packet\n"); + else + DMSG("%s: short packet sent len:%d," + "length:%d,actual:%d\n", __FUNCTION__, + tmp, req->req.length, req->req.actual); + req->req.actual = req->req.length; + completed = 1; + /* There are still packets to transfer */ + } else if ( ep->dma_con) { + DMSG("%s: more packets,length:%d,actual:%d\n", + __FUNCTION__,req->req.length, + req->req.actual); + req->req.actual += ep->usb_ep->maxpacket; + completed = 0; + } else { + DMSG("%s: no more packets,length:%d," + "actual:%d\n", __FUNCTION__, + req->req.length, req->req.actual); + req->req.actual = req->req.length; + completed = 1; + } + } else { + req->req.actual = req->req.length; + completed = 1; + } + } else if (dcsr & DCSR_EORINTR) { //DCSR_ENRINTR) { //Only happened in OUT DMA + int remain,udccsr ; + + DCSR(dmach) = DCSR_EORINTR; //DCSR_ENRINTR; + remain = DCMD(dmach) & DCMD_LENGTH; + req->req.actual = req->req.length - remain; + + udccsr = *ep->reg_udccsr; + if (udccsr & UDCCSR_SP) { + *ep->reg_udccsr = UDCCSR_PC | (udccsr & UDCCSR_MASK); + completed = 1; + } + DMSG("%s: length:%d actual:%d\n", + __FUNCTION__, req->req.length, req->req.actual); + } else + DMSG("%s: Others dma:%d DCSR:0x%x DCMD:0x%x\n", + __FUNCTION__, dmach, DCSR(dmach), DCMD(dmach)); + + if (likely(completed)) { + if (req->queue.next != &ep->queue) { + req_next = list_entry(req->queue.next, + struct pxa27x_request, queue); + kick_dma(ep, req_next); + } + done(ep, req, 0); + } else { + kick_dma(ep, req); + } + + local_irq_enable(); +} + +#endif +/*-------------------------------------------------------------------------*/ + +static int +pxa27x_ep_queue(struct usb_ep *_ep, struct usb_request *_req, unsigned gfp_flags) +{ + struct pxa27x_virt_ep *virt_ep; + struct pxa27x_ep *ep; + struct pxa27x_request *req; + struct pxa27x_udc *dev; + unsigned long flags; + + virt_ep = container_of(_ep, struct pxa27x_virt_ep, usb_ep); + ep = virt_ep->pxa_ep; + + req = container_of(_req, struct pxa27x_request, req); + if (unlikely (!_req || !_req->complete || !_req->buf|| + !list_empty(&req->queue))) { + DMSG("%s, bad params\n", __FUNCTION__); + return -EINVAL; + } + + if (unlikely (!_ep || (!ep->desc && _ep->name != ep0name))) { + DMSG("%s, bad ep\n", __FUNCTION__); + return -EINVAL; + } + + DMSG("%s, ep point %d is queue\n", __FUNCTION__, ep->ep_num); + + dev = ep->dev; + if (unlikely (!dev->driver + || dev->gadget.speed == USB_SPEED_UNKNOWN)) { + DMSG("%s, bogus device state\n", __FUNCTION__); + return -ESHUTDOWN; + } + + /* iso is always one packet per request, that's the only way + * we can report per-packet status. that also helps with dma. + */ + if (unlikely (ep->ep_type == USB_ENDPOINT_XFER_ISOC + && req->req.length > le16_to_cpu + (ep->desc->wMaxPacketSize))) + return -EMSGSIZE; + + +#ifdef USE_DMA + // FIXME caller may already have done the dma mapping + if (ep->dma >= 0) { + _req->dma = dma_map_single(dev->dev, _req->buf, _req->length, + (ep->dir_in) ? DMA_TO_DEVICE : DMA_FROM_DEVICE); + } +#endif + + DBG(DBG_NOISY, "%s queue req %p, len %d buf %p\n", + _ep->name, _req, _req->length, _req->buf); + + local_irq_save(flags); + + _req->status = -EINPROGRESS; + _req->actual = 0; + + /* kickstart this i/o queue? */ + if (list_empty(&ep->queue) && !ep->stopped) { + if (ep->desc == 0 /* ep0 */) { + unsigned length = _req->length; + + switch (dev->ep0state) { + case EP0_IN_DATA_PHASE: + dev->stats.write.ops++; + if (write_ep0_fifo(ep, req)) + req = 0; + break; + + case EP0_OUT_DATA_PHASE: + dev->stats.read.ops++; + if (dev->req_pending) + ep0start(dev, UDCCSR0_IPR, "OUT"); + if (length == 0 || ((UDCCSR0 & UDCCSR0_RNE) != 0 + && read_ep0_fifo(ep, req))) { + ep0_idle(dev); + done(ep, req, 0); + req = 0; + } + break; + case EP0_NO_ACTION: + ep0_idle(dev); + req=0; + break; + default: + DMSG("ep0 i/o, odd state %d\n", dev->ep0state); + local_irq_restore (flags); + return -EL2HLT; + } + +#ifdef USE_DMA + /* either start dma or prime pio pump */ + } else if (ep->dma >= 0) { + kick_dma(ep, req); +#endif + /* can the FIFO can satisfy the request immediately? */ + } else if (ep->dir_in && (*ep->reg_udccsr & UDCCSR_FS) != 0 + && write_fifo(ep, req)) { + req = 0; + } else if ((*ep->reg_udccsr & UDCCSR_FS) != 0 + && read_fifo(ep, req)) { + req = 0; + } + DMSG("req:%p,ep->desc:%p,ep->dma:%d\n", req, ep->desc, ep->dma); + if (likely (req && ep->desc) && ep->dma < 0) + pio_irq_enable(ep->pxa_ep_num); + } + + /* pio or dma irq handler advances the queue. */ + if (likely (req != 0)) + list_add_tail(&req->queue, &ep->queue); + local_irq_restore(flags); + + return 0; +} + + +/* + * nuke - dequeue ALL requests + */ +static void nuke(struct pxa27x_ep *ep, int status) +{ + struct pxa27x_request *req; + + /* called with irqs blocked */ +#ifdef USE_DMA + if (ep->dma >= 0 && !ep->stopped) + cancel_dma(ep); +#endif + while (!list_empty(&ep->queue)) { + req = list_entry(ep->queue.next, struct pxa27x_request, queue); + done(ep, req, status); + } + if (ep->desc) + pio_irq_disable(ep->pxa_ep_num); +} + + +/* dequeue JUST ONE request */ +static int pxa27x_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) +{ + struct pxa27x_virt_ep *virt_ep = container_of(_ep, struct pxa27x_virt_ep, usb_ep); + struct pxa27x_ep *ep = virt_ep->pxa_ep; + struct pxa27x_request *req; + unsigned long flags; + + if (!_ep || _ep->name == ep0name) + return -EINVAL; + + local_irq_save(flags); + + /* make sure it's actually queued on this endpoint */ + list_for_each_entry(req, &ep->queue, queue) { + if (&req->req == _req) + break; + } + if (&req->req != _req) { + local_irq_restore(flags); + return -EINVAL; + } + +#ifdef USE_DMA + if (ep->dma >= 0 && ep->queue.next == &req->queue && !ep->stopped) { + cancel_dma(ep); + done(ep, req, -ECONNRESET); + /* restart i/o */ + if (!list_empty(&ep->queue)) { + req = list_entry(ep->queue.next, + struct pxa27x_request, queue); + kick_dma(ep, req); + } + } else +#endif + done(ep, req, -ECONNRESET); + + local_irq_restore(flags); + return 0; +} + +/*-------------------------------------------------------------------------*/ + +static int pxa27x_ep_set_halt(struct usb_ep *_ep, int value) +{ + struct pxa27x_virt_ep *virt_ep = container_of(_ep, struct pxa27x_virt_ep, usb_ep); + struct pxa27x_ep *ep = virt_ep->pxa_ep; + unsigned long flags; + + DMSG("%s is called\n", __FUNCTION__); + if (unlikely (!_ep || (!ep->desc && _ep->name != ep0name)) + || ep->ep_type == USB_ENDPOINT_XFER_ISOC) { + DMSG("%s, bad ep\n", __FUNCTION__); + return -EINVAL; + } + if (value == 0) { + /* this path (reset toggle+halt) is needed to implement + * SET_INTERFACE on normal hardware. but it can't be + * done from software on the PXA UDC, and the hardware + * forgets to do it as part of SET_INTERFACE automagic. + */ + DMSG("only host can clear %s halt\n", _ep->name); + return -EROFS; + } + + local_irq_save(flags); + + if (ep->dir_in && ((*ep->reg_udccsr & UDCCSR_FS) == 0 + || !list_empty(&ep->queue))) { + local_irq_restore(flags); + return -EAGAIN; + } + + /* FST bit is the same for control, bulk in, bulk out, interrupt in */ + *ep->reg_udccsr = UDCCSR_FST|UDCCSR_FEF; + + /* ep0 needs special care */ + if (!ep->desc) { + start_watchdog(ep->dev); + ep->dev->req_pending = 0; + ep->dev->ep0state = EP0_STALL; + + /* and bulk/intr endpoints like dropping stalls too */ + } else { + unsigned i; + for (i = 0; i < 1000; i += 20) { + if (*ep->reg_udccsr & UDCCSR_SST) + break; + udelay(20); + } + } + local_irq_restore(flags); + + DBG(DBG_VERBOSE, "%s halt\n", _ep->name); + return 0; +} + +static int pxa27x_ep_fifo_status(struct usb_ep *_ep) +{ + struct pxa27x_virt_ep *virt_ep = container_of(_ep, struct pxa27x_virt_ep, usb_ep); + struct pxa27x_ep *ep = virt_ep->pxa_ep; + + if (!_ep) { + DMSG("%s, bad ep\n", __FUNCTION__); + return -ENODEV; + } + /* pxa can't report unclaimed bytes from IN fifos */ + if (ep->dir_in) + return -EOPNOTSUPP; + if (ep->dev->gadget.speed == USB_SPEED_UNKNOWN + || (*ep->reg_udccsr & UDCCSR_FS) == 0) + return 0; + else + return (*ep->reg_udcbcr & 0xfff) + 1; +} + +static void pxa27x_ep_fifo_flush(struct usb_ep *_ep) +{ + struct pxa27x_virt_ep *virt_ep = container_of(_ep, struct pxa27x_virt_ep, usb_ep); + struct pxa27x_ep *ep = virt_ep->pxa_ep; + + DMSG("pxa27x_ep_fifo_flush\n"); + + if (!_ep || _ep->name == ep0name || !list_empty(&ep->queue)) { + DMSG("%s, bad ep\n", __FUNCTION__); + return; + } + + /* toggle and halt bits stay unchanged */ + + /* for OUT, just read and discard the FIFO contents. */ + if (!ep->dir_in) { + while (((*ep->reg_udccsr) & UDCCSR_BNE) != 0) + (void) *ep->reg_udcdr; + return; + } + + /* most IN status is the same, but ISO can't stall */ + *ep->reg_udccsr = UDCCSR_PC|UDCCSR_FST|UDCCSR_TRN + | (ep->ep_type == USB_ENDPOINT_XFER_ISOC) + ? 0 : UDCCSR_SST; +} + + +static struct usb_ep_ops pxa27x_ep_ops = { + .enable = pxa27x_ep_enable, + .disable = pxa27x_ep_disable, + + .alloc_request = pxa27x_ep_alloc_request, + .free_request = pxa27x_ep_free_request, + +// .alloc_buffer = pxa27x_ep_alloc_buffer, +// .free_buffer = pxa27x_ep_free_buffer, + + .queue = pxa27x_ep_queue, + .dequeue = pxa27x_ep_dequeue, + + .set_halt = pxa27x_ep_set_halt, + .fifo_status = pxa27x_ep_fifo_status, + .fifo_flush = pxa27x_ep_fifo_flush, +}; + + +/* --------------------------------------------------------------------------- + * device-scoped parts of the api to the usb controller hardware + * --------------------------------------------------------------------------- + */ + +static inline unsigned int validate_fifo_size(u8 bmAttributes) +{ + switch (bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + case USB_ENDPOINT_XFER_CONTROL: + return EP0_FIFO_SIZE; + break; + case USB_ENDPOINT_XFER_ISOC: + return ISO_FIFO_SIZE; + break; + case USB_ENDPOINT_XFER_BULK: + return BULK_FIFO_SIZE; + break; + case USB_ENDPOINT_XFER_INT: + return INT_FIFO_SIZE; + break; + default: + break; + } +} + +static void pxa27x_ep_free(struct usb_gadget *gadget, struct usb_ep *_ep) +{ + struct pxa27x_udc *dev = the_controller; + struct pxa27x_virt_ep *virt_ep; + int i; + + virt_ep = container_of(_ep, struct pxa27x_virt_ep, usb_ep); + + for (i = 1; i < UDC_EP_NUM; i++) { + if (dev->ep[i].usb_ep == &virt_ep->usb_ep) { + if (dev->ep[i].desc) { + virt_ep->pxa_ep = &dev->ep[i]; + pxa27x_ep_disable(&virt_ep->usb_ep); + } + dev->ep[i].usb_ep = NULL; + } + } + + if (!list_empty(&virt_ep->usb_ep.ep_list)) + list_del_init(&virt_ep->usb_ep.ep_list); + + kfree(virt_ep->usb_ep.name); + kfree(virt_ep); +} + +static void pxa27x_ep_freeall(struct usb_gadget *gadget) +{ + struct pxa27x_udc *dev = the_controller; + int i; + + for (i = 1; i < UDC_EP_NUM; i++) { + if(dev->ep[i].usb_ep) + pxa27x_ep_free(gadget, dev->ep[i].usb_ep); + } +} + +#define NAME_SIZE 18 + +static int pxa27x_find_free_ep(struct pxa27x_udc *dev) +{ + int i; + for (i = 1; i < UDC_EP_NUM; i++) { + if(!dev->ep[i].assigned) + return i; + } + return -1; +} + +/* + * Endpoint Allocation/Configuration + * + * pxa27x endpoint configuration is fixed when the device is enabled. Any pxa + * endpoint is only active in one configuration, interface and alternate + * interface combination so to support gadget drivers, we map one usb_ep to + * one of several pxa ep's. One pxa endpoint is assigned per configuration + * combination. + */ +static struct usb_ep* pxa27x_ep_alloc(struct usb_gadget *gadget, struct usb_endpoint_descriptor *desc, + struct usb_endpoint_config *epconfig, int configs) +{ + struct pxa27x_udc *dev = the_controller; + struct pxa27x_virt_ep *virt_ep; + unsigned int i, fifo_size; + char *name; + + if (unlikely(configs < 1)) { + dev_err(dev->dev, "%s: Error in config data\n", __FUNCTION__); + return NULL; + } + + virt_ep = kmalloc(sizeof(struct pxa27x_virt_ep), GFP_KERNEL); + name = kmalloc(NAME_SIZE, GFP_KERNEL); + if (!virt_ep || !name) { + dev_err(dev->dev, "%s: -ENOMEM\n", __FUNCTION__); + kfree(name); + kfree(virt_ep); + return NULL; + } + + if (!(desc->wMaxPacketSize)) { + fifo_size = validate_fifo_size(desc->bmAttributes); + desc->wMaxPacketSize = fifo_size; + } else { + fifo_size = desc->wMaxPacketSize; + } + + DMSG("pxa27x_ep_alloc: bLength: %d, bDescriptorType: %x, bEndpointAddress: %x,\n" + " bmAttributes: %x, wMaxPacketSize: %d\n", desc->bLength, + desc->bDescriptorType, desc->bEndpointAddress, desc->bmAttributes, + desc->wMaxPacketSize); + + if (!(desc->bEndpointAddress & 0xF)) + desc->bEndpointAddress |= dev->ep_num; + + for (i = 0; i < configs; i++) + { + struct pxa27x_ep *pxa_ep; + int j; + + DMSG("pxa27x_ep_alloc: config: %d, interface: %d, altinterface: %x,\n", + epconfig->config, epconfig->interface, epconfig->altinterface); + + j = pxa27x_find_free_ep(dev); + + if (unlikely(j < 0)) { + dev_err(dev->dev, "pxa27x_ep_alloc: Failed to find a spare endpoint\n"); + pxa27x_ep_free(gadget, &virt_ep->usb_ep); + return NULL; + } + + pxa_ep = &dev->ep[j]; + + if (i == 0) + virt_ep->pxa_ep = pxa_ep; + + pxa_ep->assigned = 1; + pxa_ep->ep_num = dev->ep_num; + pxa_ep->pxa_ep_num = j; + pxa_ep->usb_ep = &virt_ep->usb_ep; + pxa_ep->dev = dev; + pxa_ep->desc = desc; + pxa_ep->pio_irqs = pxa_ep->dma_irqs = 0; + pxa_ep->dma = -1; + + pxa_ep->fifo_size = fifo_size; + pxa_ep->dir_in = (desc->bEndpointAddress & USB_DIR_IN) ? 1 : 0; + pxa_ep->ep_type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + pxa_ep->stopped = 1; + pxa_ep->dma_con = 0; +// pxa_ep->config = epconfig->config; +// pxa_ep->interface = epconfig->interface; +// pxa_ep->aisn = epconfig->altinterface; + + pxa_ep->reg_udccsr = &UDCCSR0 + j; + pxa_ep->reg_udcbcr = &UDCBCR0 + j; + pxa_ep->reg_udcdr = &UDCDR0 + j ; + pxa_ep->reg_udccr = &UDCCRA - 1 + j; +#ifdef USE_DMA + pxa_ep->reg_drcmr = &DRCMR24 + j; +#endif + + /* Configure UDCCR */ + *pxa_ep->reg_udccr = ((pxa_ep->config << UDCCONR_CN_S) & UDCCONR_CN) + | ((pxa_ep->interface << UDCCONR_IN_S) & UDCCONR_IN) + | ((pxa_ep->aisn << UDCCONR_AISN_S) & UDCCONR_AISN) + | ((dev->ep_num << UDCCONR_EN_S) & UDCCONR_EN) + | ((pxa_ep->ep_type << UDCCONR_ET_S) & UDCCONR_ET) + | ((pxa_ep->dir_in) ? UDCCONR_ED : 0) + | ((min(pxa_ep->fifo_size, (unsigned)desc->wMaxPacketSize) << UDCCONR_MPS_S ) & UDCCONR_MPS) + | UDCCONR_EE; +// | UDCCONR_DE | UDCCONR_EE; + + + +#ifdef USE_DMA + /* Only BULK use DMA */ + if ((pxa_ep->ep_type & USB_ENDPOINT_XFERTYPE_MASK)\ + == USB_ENDPOINT_XFER_BULK) + *pxa_ep->reg_udccsr = UDCCSR_DME; +#endif + + DMSG("UDCCR: 0x%p is 0x%x\n", pxa_ep->reg_udccr,*pxa_ep->reg_udccr); + + epconfig++; + } + + /* Fill ep name*/ + switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + case USB_ENDPOINT_XFER_BULK: + sprintf(name, "ep%d%s-bulk", dev->ep_num, + ((desc->bEndpointAddress & USB_DIR_IN) ? "in":"out")); + break; + case USB_ENDPOINT_XFER_INT: + sprintf(name, "ep%d%s-intr", dev->ep_num, + ((desc->bEndpointAddress & USB_DIR_IN) ? "in":"out")); + break; + default: + sprintf(name, "ep%d%s", dev->ep_num, + ((desc->bEndpointAddress & USB_DIR_IN) ? "in":"out")); + break; + } + + virt_ep->desc = desc; + virt_ep->usb_ep.name = name; + virt_ep->usb_ep.ops = &pxa27x_ep_ops; + virt_ep->usb_ep.maxpacket = min((ushort)fifo_size, desc->wMaxPacketSize); + + list_add_tail(&virt_ep->usb_ep.ep_list, &gadget->ep_list); + + dev->ep_num++; + return &virt_ep->usb_ep; +} + +static int pxa27x_udc_get_frame(struct usb_gadget *_gadget) +{ + return (UDCFNR & 0x7FF); +} + +static int pxa27x_udc_wakeup(struct usb_gadget *_gadget) +{ + /* host may not have enabled remote wakeup */ + if ((UDCCR & UDCCR_DWRE) == 0) + return -EHOSTUNREACH; + udc_set_mask_UDCCR(UDCCR_UDR); + return 0; +} + +static const struct usb_gadget_ops pxa27x_udc_ops = { + .ep_alloc = pxa27x_ep_alloc, + .get_frame = pxa27x_udc_get_frame, + .wakeup = pxa27x_udc_wakeup, + // current versions must always be self-powered +}; + + +/*-------------------------------------------------------------------------*/ + +#ifdef UDC_PROC_FILE + +static const char proc_node_name [] = "driver/udc"; + +static int +udc_proc_read(char *page, char **start, off_t off, int count, + int *eof, void *_dev) +{ + char *buf = page; + struct pxa27x_udc *dev = _dev; + char *next = buf; + unsigned size = count; + unsigned long flags; + int i, t; + u32 tmp; + + if (off != 0) + return 0; + + local_irq_save(flags); + + /* basic device status */ + t = scnprintf(next, size, DRIVER_DESC "\n" + "%s version: %s\nGadget driver: %s\n", + driver_name, DRIVER_VERSION DMASTR, + dev->driver ? dev->driver->driver.name : "(none)"); + size -= t; + next += t; + + /* registers for device and ep0 */ + t = scnprintf(next, size, + "uicr %02X.%02X, usir %02X.%02x, ufnr %02X\n", + UDCICR1, UDCICR0, UDCISR1, UDCISR0, UDCFNR); + size -= t; + next += t; + + tmp = UDCCR; + t = scnprintf(next, size,"udccr %02X =%s%s%s%s%s%s%s%s%s%s, con=%d,inter=%d,altinter=%d\n", tmp, + (tmp & UDCCR_OEN) ? " oen":"", + (tmp & UDCCR_AALTHNP) ? " aalthnp":"", + (tmp & UDCCR_AHNP) ? " rem" : "", + (tmp & UDCCR_BHNP) ? " rstir" : "", + (tmp & UDCCR_DWRE) ? " dwre" : "", + (tmp & UDCCR_SMAC) ? " smac" : "", + (tmp & UDCCR_EMCE) ? " emce" : "", + (tmp & UDCCR_UDR) ? " udr" : "", + (tmp & UDCCR_UDA) ? " uda" : "", + (tmp & UDCCR_UDE) ? " ude" : "", + (tmp & UDCCR_ACN) >> UDCCR_ACN_S, + (tmp & UDCCR_AIN) >> UDCCR_AIN_S, + (tmp & UDCCR_AAISN)>> UDCCR_AAISN_S ); + + size -= t; + next += t; + + tmp = UDCCSR0; + t = scnprintf(next, size, + "udccsr0 %02X =%s%s%s%s%s%s%s\n", tmp, + (tmp & UDCCSR0_SA) ? " sa" : "", + (tmp & UDCCSR0_RNE) ? " rne" : "", + (tmp & UDCCSR0_FST) ? " fst" : "", + (tmp & UDCCSR0_SST) ? " sst" : "", + (tmp & UDCCSR0_DME) ? " dme" : "", + (tmp & UDCCSR0_IPR) ? " ipr" : "", + (tmp & UDCCSR0_OPC) ? " opc" : ""); + size -= t; + next += t; + + if (!dev->driver) + goto done; + + t = scnprintf(next, size, "ep0 IN %lu/%lu, OUT %lu/%lu\nirqs %lu\n\n", + dev->stats.write.bytes, dev->stats.write.ops, + dev->stats.read.bytes, dev->stats.read.ops, + dev->stats.irqs); + size -= t; + next += t; + + /* dump endpoint queues */ + for (i = 0; i < UDC_EP_NUM; i++) { + struct pxa27x_ep *ep = &dev->ep [i]; + struct pxa27x_request *req; + int t; + + if (i != 0) { + const struct usb_endpoint_descriptor *d; + + d = ep->desc; + if (!d) + continue; + tmp = *dev->ep [i].reg_udccsr; + t = scnprintf(next, size, + "%d max %d %s udccs %02x udccr:0x%x\n", + i, le16_to_cpu (d->wMaxPacketSize), + (ep->dma >= 0) ? "dma" : "pio", tmp, + *dev->ep[i].reg_udccr); + /* TODO translate all five groups of udccs bits! */ + + } else /* ep0 should only have one transfer queued */ + t = scnprintf(next, size, "ep0 max 16 pio irqs %lu\n", + ep->pio_irqs); + if (t <= 0 || t > size) + goto done; + size -= t; + next += t; + + if (list_empty(&ep->queue)) { + t = scnprintf(next, size, "\t(nothing queued)\n"); + if (t <= 0 || t > size) + goto done; + size -= t; + next += t; + continue; + } + list_for_each_entry(req, &ep->queue, queue) { +#ifdef 0 +//#ifdef USE_DMA + if (ep->dma >= 0 && req->queue.prev == &ep->queue) + t = scnprintf(next, size, "\treq %p len %d/%d " + "buf %p (dma%d dcmd %08x)\n", + &req->req, req->req.actual, + req->req.length, req->req.buf, + ep->dma, DCMD(ep->dma) + /* low 13 bits == bytes-to-go */); + else +#endif + t = scnprintf(next, size, + "\treq %p len %d/%d buf %p\n", + &req->req, req->req.actual, + req->req.length, req->req.buf); + if (t <= 0 || t > size) + goto done; + size -= t; + next += t; + } + } + +done: + local_irq_restore(flags); + *eof = 1; + return count - size; +} + +#define create_proc_files() \ + create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev) +#define remove_proc_files() \ + remove_proc_entry(proc_node_name, NULL) + +#else /* !UDC_PROC_FILE */ +#define create_proc_files() do {} while (0) +#define remove_proc_files() do {} while (0) + +#endif /* UDC_PROC_FILE */ + +/*-------------------------------------------------------------------------*/ +static ssize_t show_function(struct device *_dev, struct device_attribute *attr, char *buf) +{ + struct pxa27x_udc *dev = dev_get_drvdata(_dev); + + if (!dev->driver || !dev->driver->function + || strlen(dev->driver->function) > PAGE_SIZE) + return 0; + return scnprintf(buf, PAGE_SIZE, "%s\n", dev->driver->function); +} +static DEVICE_ATTR(function, S_IRUGO, show_function, NULL); + +/*-------------------------------------------------------------------------*/ + +/* + * udc_disable - disable USB device controller + */ +static void udc_disable(struct pxa27x_udc *dev) +{ + UDCICR0 = UDCICR1 = 0x00000000; + + udc_clear_mask_UDCCR(UDCCR_UDE); + + /* Disable clock for USB device */ + pxa_set_cken(CKEN_USB, 0); + + ep0_idle(dev); + dev->gadget.speed = USB_SPEED_UNKNOWN; + if (dev->mach && dev->mach->udc_command) + dev->mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT); +} + + +/* + * udc_reinit - initialize software state + */ +static void udc_reinit(struct pxa27x_udc *dev) +{ + u32 i; + + dev->ep0state = EP0_IDLE; + + /* basic endpoint records init */ + for (i = 0; i < UDC_EP_NUM; i++) { + struct pxa27x_ep *ep = &dev->ep[i]; + + ep->stopped = 0; + ep->pio_irqs = ep->dma_irqs = 0; + } + dev->configuration = 0; + dev->interface = 0; + dev->alternate = 0; + /* the rest was statically initialized, and is read-only */ +} + +/* until it's enabled, this UDC should be completely invisible + * to any USB host. + */ +static void udc_enable(struct pxa27x_udc *dev) +{ + udc_clear_mask_UDCCR(UDCCR_UDE); + + /* Enable clock for USB device */ + pxa_set_cken(CKEN_USB, 1); + + UDCICR0 = UDCICR1 = 0; + + ep0_idle(dev); + dev->gadget.speed = USB_SPEED_FULL; + dev->stats.irqs = 0; + + udc_set_mask_UDCCR(UDCCR_UDE); + udelay(2); + if (UDCCR & UDCCR_EMCE) + dev_err(dev->dev, "There are error in configuration, udc disabled\n"); + + /* caller must be able to sleep in order to cope + * with startup transients. + */ + msleep(100); + + /* enable suspend/resume and reset irqs */ + UDCICR1 = UDCICR1_IECC | UDCICR1_IERU | UDCICR1_IESU | UDCICR1_IERS; + + /* enable ep0 irqs */ + UDCICR0 = UDCICR_INT(0,UDCICR_INT_MASK); + + DMSG("Connecting\n"); + /* RPFIXME */ + UP2OCR = UP2OCR_HXOE | UP2OCR_DPPUE | UP2OCR_DPPUBE; + + if (dev->mach && dev->mach->udc_command) + dev->mach->udc_command(PXA2XX_UDC_CMD_CONNECT); +} + + +/* when a driver is successfully registered, it will receive + * control requests including set_configuration(), which enables + * non-control requests. then usb traffic follows until a + * disconnect is reported. then a host may connect again, or + * the driver might get unbound. + */ +int usb_gadget_register_driver(struct usb_gadget_driver *driver) +{ + struct pxa27x_udc *dev = the_controller; + int retval; + + if (!driver + || driver->speed < USB_SPEED_FULL + || !driver->bind + || !driver->disconnect + || !driver->setup) + return -EINVAL; + if (!dev) + return -ENODEV; + if (dev->driver) + return -EBUSY; + + udc_disable(dev); + udc_init_ep(dev); + udc_reinit(dev); + + /* first hook up the driver ... */ + dev->driver = driver; + dev->gadget.dev.driver = &driver->driver; + dev->ep_num = 1; + + retval = device_add (&dev->gadget.dev); + if (retval) { +fail: + dev->driver = NULL; + dev->gadget.dev.driver = NULL; + return retval; + } + retval = driver->bind(&dev->gadget); + if (retval) { + DMSG("bind to driver %s --> error %d\n", + driver->driver.name, retval); + device_del(&dev->gadget.dev); + goto fail; + } + device_create_file(dev->dev, &dev_attr_function); + + /* ... then enable host detection and ep0; and we're ready + * for set_configuration as well as eventual disconnect. + * NOTE: this shouldn't power up until later. + */ + DMSG("registered gadget driver '%s'\n", driver->driver.name); + udc_enable(dev); + dump_state(dev); + return 0; +} +EXPORT_SYMBOL(usb_gadget_register_driver); + +static void +stop_activity(struct pxa27x_udc *dev, struct usb_gadget_driver *driver) +{ + int i; + + DMSG("Trace path 1\n"); + /* don't disconnect drivers more than once */ + if (dev->gadget.speed == USB_SPEED_UNKNOWN) + driver = 0; + dev->gadget.speed = USB_SPEED_UNKNOWN; + + /* prevent new request submissions, kill any outstanding requests */ + for (i = 0; i < UDC_EP_NUM; i++) { + struct pxa27x_ep *ep = &dev->ep[i]; + + ep->stopped = 1; + nuke(ep, -ESHUTDOWN); + } + del_timer_sync(&dev->timer); + + /* report disconnect; the driver is already quiesced */ + if (driver) + driver->disconnect(&dev->gadget); + + /* re-init driver-visible data structures */ + udc_reinit(dev); +} + +int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) +{ + struct pxa27x_udc *dev = the_controller; + + if (!dev) + return -ENODEV; + if (!driver || driver != dev->driver || !driver->unbind) + return -EINVAL; + + local_irq_disable(); + udc_disable(dev); + stop_activity(dev, driver); + local_irq_enable(); + + driver->unbind(&dev->gadget); + pxa27x_ep_freeall(&dev->gadget); + dev->driver = 0; + + device_del(&dev->gadget.dev); + device_remove_file(dev->dev, &dev_attr_function); + + DMSG("unregistered gadget driver '%s'\n", driver->driver.name); + dump_state(dev); + return 0; +} +EXPORT_SYMBOL(usb_gadget_unregister_driver); + +#ifndef enable_disconnect_irq +#define enable_disconnect_irq() do {} while (0) +#define disable_disconnect_irq() do {} while (0) +#endif + + +/*-------------------------------------------------------------------------*/ + +static inline void clear_ep_state(struct pxa27x_udc *dev) +{ + unsigned i; + + /* hardware SET_{CONFIGURATION,INTERFACE} automagic resets endpoint + * fifos, and pending transactions mustn't be continued in any case. + */ + for (i = 1; i < UDC_EP_NUM; i++) + nuke(&dev->ep[i], -ECONNABORTED); +} + +static void udc_watchdog(unsigned long _dev) +{ + struct pxa27x_udc *dev = (void *)_dev; + + local_irq_disable(); + if (dev->ep0state == EP0_STALL + && (UDCCSR0 & UDCCSR0_FST) == 0 + && (UDCCSR0 & UDCCSR0_SST) == 0) { + UDCCSR0 = UDCCSR0_FST|UDCCSR0_FTF; + DBG(DBG_VERBOSE, "ep0 re-stall\n"); + start_watchdog(dev); + } + local_irq_enable(); +} + +static void handle_ep0(struct pxa27x_udc *dev) +{ + u32 udccsr0 = UDCCSR0; + struct pxa27x_ep *ep = &dev->ep[0]; + struct pxa27x_request *req; + union { + struct usb_ctrlrequest r; + u8 raw[8]; + u32 word[2]; + } u; + + if (list_empty(&ep->queue)) + req = 0; + else + req = list_entry(ep->queue.next, struct pxa27x_request, queue); + + /* clear stall status */ + if (udccsr0 & UDCCSR0_SST) { + nuke(ep, -EPIPE); + UDCCSR0 = UDCCSR0_SST; + del_timer(&dev->timer); + ep0_idle(dev); + } + + /* previous request unfinished? non-error iff back-to-back ... */ + if ((udccsr0 & UDCCSR0_SA) != 0 && dev->ep0state != EP0_IDLE) { + nuke(ep, 0); + del_timer(&dev->timer); + ep0_idle(dev); + } + + switch (dev->ep0state) { + case EP0_NO_ACTION: + dev_info(dev->dev, "%s: Busy\n", __FUNCTION__); + /*Fall through */ + case EP0_IDLE: + /* late-breaking status? */ + udccsr0 = UDCCSR0; + + /* start control request? */ + if (likely((udccsr0 & (UDCCSR0_OPC|UDCCSR0_SA|UDCCSR0_RNE)) + == (UDCCSR0_OPC|UDCCSR0_SA|UDCCSR0_RNE))) { + int i; + + nuke(ep, -EPROTO); + /* read SETUP packet */ + for (i = 0; i < 2; i++) { + if (unlikely(!(UDCCSR0 & UDCCSR0_RNE))) { +bad_setup: + DMSG("SETUP %d!\n", i); + goto stall; + } + u.word [i] = UDCDR0; + } + if (unlikely((UDCCSR0 & UDCCSR0_RNE) != 0)) + goto bad_setup; + + le16_to_cpus(&u.r.wValue); + le16_to_cpus(&u.r.wIndex); + le16_to_cpus(&u.r.wLength); + + DBG(DBG_VERBOSE, "SETUP %02x.%02x v%04x i%04x l%04x\n", + u.r.bRequestType, u.r.bRequest, + u.r.wValue, u.r.wIndex, u.r.wLength); + /* cope with automagic for some standard requests. */ + dev->req_std = (u.r.bRequestType & USB_TYPE_MASK) + == USB_TYPE_STANDARD; + dev->req_config = 0; + dev->req_pending = 1; +#if 0 + switch (u.r.bRequest) { + /* hardware was supposed to hide this */ + case USB_REQ_SET_CONFIGURATION: + case USB_REQ_SET_INTERFACE: + case USB_REQ_SET_ADDRESS: + dev_err(dev->dev, "Should not come here\n"); + break; + } + +#endif + if (u.r.bRequestType & USB_DIR_IN) + dev->ep0state = EP0_IN_DATA_PHASE; + else + dev->ep0state = EP0_OUT_DATA_PHASE; + i = dev->driver->setup(&dev->gadget, &u.r); + + if (i < 0) { + /* hardware automagic preventing STALL... */ + if (dev->req_config) { + /* hardware sometimes neglects to tell + * tell us about config change events, + * so later ones may fail... + */ + WARN("config change %02x fail %d?\n", + u.r.bRequest, i); + return; + /* TODO experiment: if has_cfr, + * hardware didn't ACK; maybe we + * could actually STALL! + */ + } + DBG(DBG_VERBOSE, "protocol STALL, " + "%02x err %d\n", UDCCSR0, i); +stall: + /* the watchdog timer helps deal with cases + * where udc seems to clear FST wrongly, and + * then NAKs instead of STALLing. + */ + ep0start(dev, UDCCSR0_FST|UDCCSR0_FTF, "stall"); + start_watchdog(dev); + dev->ep0state = EP0_STALL; + + /* deferred i/o == no response yet */ + } else if (dev->req_pending) { + if (likely(dev->ep0state == EP0_IN_DATA_PHASE + || dev->req_std || u.r.wLength)) + ep0start(dev, 0, "defer"); + else + ep0start(dev, UDCCSR0_IPR, "defer/IPR"); + } + + /* expect at least one data or status stage irq */ + return; + + } else { + /* some random early IRQ: + * - we acked FST + * - IPR cleared + * - OPC got set, without SA (likely status stage) + */ + UDCCSR0 = udccsr0 & (UDCCSR0_SA|UDCCSR0_OPC); + } + break; + case EP0_IN_DATA_PHASE: /* GET_DESCRIPTOR etc */ + if (udccsr0 & UDCCSR0_OPC) { + UDCCSR0 = UDCCSR0_OPC|UDCCSR0_FTF; + DBG(DBG_VERBOSE, "ep0in premature status\n"); + if (req) + done(ep, req, 0); + ep0_idle(dev); + } else /* irq was IPR clearing */ { + if (req) { + /* this IN packet might finish the request */ + (void) write_ep0_fifo(ep, req); + } /* else IN token before response was written */ + } + break; + case EP0_OUT_DATA_PHASE: /* SET_DESCRIPTOR etc */ + if (udccsr0 & UDCCSR0_OPC) { + if (req) { + /* this OUT packet might finish the request */ + if (read_ep0_fifo(ep, req)) + done(ep, req, 0); + /* else more OUT packets expected */ + } /* else OUT token before read was issued */ + } else /* irq was IPR clearing */ { + DBG(DBG_VERBOSE, "ep0out premature status\n"); + if (req) + done(ep, req, 0); + ep0_idle(dev); + } + break; + case EP0_STALL: + UDCCSR0 = UDCCSR0_FST; + break; + } + UDCISR0 = UDCISR_INT(0, UDCISR_INT_MASK); +} + + +static void handle_ep(struct pxa27x_ep *ep) +{ + struct pxa27x_request *req; + int completed; + u32 udccsr=0; + + DMSG("%s is called\n", __FUNCTION__); + do { + completed = 0; + if (likely (!list_empty(&ep->queue))) { + req = list_entry(ep->queue.next, + struct pxa27x_request, queue); + } else + req = 0; + +// udccsr = *ep->reg_udccsr; + DMSG("%s: req:%p, udcisr0:0x%x udccsr %p:0x%x\n", __FUNCTION__, + req, UDCISR0, ep->reg_udccsr, *ep->reg_udccsr); + if (unlikely(ep->dir_in)) { + udccsr = (UDCCSR_SST | UDCCSR_TRN) & *ep->reg_udccsr; + if (unlikely (udccsr)) + *ep->reg_udccsr = udccsr; + + if (req && likely ((*ep->reg_udccsr & UDCCSR_FS) != 0)) + completed = write_fifo(ep, req); + + } else { + udccsr = (UDCCSR_SST | UDCCSR_TRN) & *ep->reg_udccsr; + if (unlikely(udccsr)) + *ep->reg_udccsr = udccsr; + + /* fifos can hold packets, ready for reading... */ + if (likely(req)) { + completed = read_fifo(ep, req); + } else { + pio_irq_disable (ep->pxa_ep_num); + *ep->reg_udccsr = UDCCSR_FEF; + DMSG("%s: no req for out data\n", + __FUNCTION__); + } + } + ep->pio_irqs++; + } while (completed); +} + +static void pxa27x_update_eps(struct pxa27x_udc *dev) +{ + struct pxa27x_virt_ep *virt_ep; + int i; + + for (i = 1; i < UDC_EP_NUM; i++) { + if(!dev->ep[i].assigned || !dev->ep[i].usb_ep) + continue; + virt_ep = container_of(dev->ep[i].usb_ep, struct pxa27x_virt_ep, usb_ep); + + DMSG("%s, Updating eps %d:%d, %d:%d, %d:%d, %p,%p\n", __FUNCTION__, dev->ep[i].config, dev->configuration + ,dev->ep[i].interface, dev->interface, dev->ep[i].aisn, dev->alternate, virt_ep->pxa_ep, &dev->ep[i]); + + if(dev->ep[i].config == dev->configuration && virt_ep->pxa_ep != &dev->ep[i]) { + if ((dev->ep[i].interface == dev->interface && + dev->ep[i].aisn == dev->alternate) || virt_ep->pxa_ep->config != dev->configuration) { + + if (virt_ep->pxa_ep->desc) { + DMSG("%s, Changing end point to %d (en/dis)\n", __FUNCTION__, i); + pxa27x_ep_disable(&virt_ep->usb_ep); + virt_ep->pxa_ep = &dev->ep[i]; + pxa27x_ep_enable(&virt_ep->usb_ep, virt_ep->desc); + } else { + DMSG("%s, Changing end point to %d (no en/dis)\n", __FUNCTION__, i); + virt_ep->pxa_ep = &dev->ep[i]; + } + } + } + } +} + +static void pxa27x_change_configuration(struct pxa27x_udc *dev) +{ + struct usb_ctrlrequest req ; + + pxa27x_update_eps(dev); + + req.bRequestType = 0; + req.bRequest = USB_REQ_SET_CONFIGURATION; + req.wValue = dev->configuration; + req.wIndex = 0; + req.wLength = 0; + + dev->ep0state = EP0_NO_ACTION; + dev->driver->setup(&dev->gadget, &req); +} + +static void pxa27x_change_interface(struct pxa27x_udc *dev) +{ + struct usb_ctrlrequest req; + + pxa27x_update_eps(dev); + + req.bRequestType = USB_RECIP_INTERFACE; + req.bRequest = USB_REQ_SET_INTERFACE; + req.wValue = dev->alternate; + req.wIndex = dev->interface; + req.wLength = 0; + + dev->ep0state = EP0_NO_ACTION; + dev->driver->setup(&dev->gadget, &req); +} + +/* + * pxa27x_udc_irq - interrupt handler + * + * avoid delays in ep0 processing. the control handshaking isn't always + * under software control (pxa250c0 and the pxa255 are better), and delays + * could cause usb protocol errors. + */ +static irqreturn_t pxa27x_udc_irq(int irq, void *_dev) +{ + struct pxa27x_udc *dev = _dev; + int handled; + + dev->stats.irqs++; + + DBG(DBG_VERBOSE, "Interrupt, UDCISR0:0x%08x, UDCISR1:0x%08x, " + "UDCCR:0x%08x\n", UDCISR0, UDCISR1, UDCCR); + do { + u32 udcir = UDCISR1 & 0xF8000000; + + handled = 0; + + /* SUSpend Interrupt Request */ + if (unlikely(udcir & UDCISR1_IRSU)) { + UDCISR1 = UDCISR1_IRSU; + handled = 1; + DBG(DBG_VERBOSE, "USB suspend\n"); + if (dev->gadget.speed != USB_SPEED_UNKNOWN + && dev->driver + && dev->driver->suspend) + dev->driver->suspend(&dev->gadget); + ep0_idle(dev); + } + + /* RESume Interrupt Request */ + if (unlikely(udcir & UDCISR1_IRRU)) { + UDCISR1 = UDCISR1_IRRU; + handled = 1; + DBG(DBG_VERBOSE, "USB resume\n"); + + if (dev->gadget.speed != USB_SPEED_UNKNOWN + && dev->driver + && dev->driver->resume) + dev->driver->resume(&dev->gadget); + } + + if (unlikely(udcir & UDCISR1_IRCC)) { + unsigned config, interface, alternate; + + handled = 1; + DBG(DBG_VERBOSE, "USB SET_CONFIGURATION or " + "SET_INTERFACE command received\n"); + + config = (UDCCR & UDCCR_ACN) >> UDCCR_ACN_S; + + if (dev->configuration != config) { + dev->configuration = config; + pxa27x_change_configuration(dev) ; + } + + interface = (UDCCR & UDCCR_AIN) >> UDCCR_AIN_S; + alternate = (UDCCR & UDCCR_AAISN) >> UDCCR_AAISN_S; + + if ((dev->interface != interface) || (dev->alternate != alternate)) { + dev->interface = interface; + dev->alternate = alternate; + pxa27x_change_interface(dev); + } + + UDCCR |= UDCCR_SMAC; + + UDCISR1 = UDCISR1_IRCC; + DMSG("%s: con:%d,inter:%d,alt:%d\n", + __FUNCTION__, config,interface, alternate); + } + + /* ReSeT Interrupt Request - USB reset */ + if (unlikely(udcir & UDCISR1_IRRS)) { + UDCISR1 = UDCISR1_IRRS; + handled = 1; + + if ((UDCCR & UDCCR_UDA) == 0) { + DBG(DBG_VERBOSE, "USB reset start\n"); + + /* reset driver and endpoints, + * in case that's not yet done + */ + stop_activity(dev, dev->driver); + } + INFO("USB reset\n"); + dev->gadget.speed = USB_SPEED_FULL; + memset(&dev->stats, 0, sizeof dev->stats); + + } else { + u32 udcisr0 = UDCISR0 ; + u32 udcisr1 = UDCISR1 & 0xFFFF; + int i; + + if (unlikely (!udcisr0 && !udcisr1)) + continue; + + DBG(DBG_VERY_NOISY, "irq %02x.%02x\n", udcisr1,udcisr0); + + /* control traffic */ + if (udcisr0 & UDCISR0_IR0) { + dev->ep[0].pio_irqs++; + handle_ep0(dev); + handled = 1; + } + + udcisr0 >>= 2; + /* endpoint data transfers */ + for (i = 1; udcisr0!=0 && i < 16; udcisr0>>=2,i++) { + UDCISR0 = UDCISR_INT(i, UDCISR_INT_MASK); + + if (udcisr0 & UDC_INT_FIFOERROR) + dev_err(dev->dev, " Endpoint %d Fifo error\n", i); + if (udcisr0 & UDC_INT_PACKETCMP) { + handle_ep(&dev->ep[i]); + handled = 1; + } + + } + + for (i = 0; udcisr1!=0 && i < 8; udcisr1 >>= 2, i++) { + UDCISR1 = UDCISR_INT(i, UDCISR_INT_MASK); + + if (udcisr1 & UDC_INT_FIFOERROR) { + dev_err(dev->dev, "Endpoint %d fifo error\n", (i+16)); + } + + if (udcisr1 & UDC_INT_PACKETCMP) { + handle_ep(&dev->ep[i+16]); + handled = 1; + } + } + } + + /* we could also ask for 1 msec SOF (SIR) interrupts */ + + } while (handled); + return IRQ_HANDLED; +} + +int write_ep0_zlp(void) +{ + UDCCSR0 = UDCCSR0_IPR; + return 0; +} +EXPORT_SYMBOL(write_ep0_zlp); + +static void udc_init_ep(struct pxa27x_udc *dev) +{ + int i; + + INIT_LIST_HEAD(&dev->gadget.ep_list); + INIT_LIST_HEAD(&dev->gadget.ep0->ep_list); + + for (i = 0; i < UDC_EP_NUM; i++) { + struct pxa27x_ep *ep = &dev->ep[i]; + + ep->dma = -1; + if (i != 0) { + memset(ep, 0, sizeof(*ep)); + } + INIT_LIST_HEAD(&ep->queue); + } +} + +/*-------------------------------------------------------------------------*/ + +static void nop_release(struct device *dev) +{ + DMSG("%s %s\n", __FUNCTION__, dev->bus_id); +} + +/* this uses load-time allocation and initialization (instead of + * doing it at run-time) to save code, eliminate fault paths, and + * be more obviously correct. + */ + +static struct pxa27x_udc memory = { + .gadget = { + .ops = &pxa27x_udc_ops, + .ep0 = &memory.virt_ep0.usb_ep, + .name = driver_name, + .dev = { + .bus_id = "gadget", + .release = nop_release, + }, + }, + + /* control endpoint */ + .virt_ep0 = { + .pxa_ep = &memory.ep[0], + .usb_ep = { + .name = ep0name, + .ops = &pxa27x_ep_ops, + .maxpacket = EP0_FIFO_SIZE, + }, + }, + + .ep[0] = { + .usb_ep = &memory.virt_ep0.usb_ep, + .dev = &memory, + .reg_udccsr = &UDCCSR0, + .reg_udcdr = &UDCDR0, + }, +}; + +static int __init pxa27x_udc_probe(struct device *_dev) +{ + struct pxa27x_udc *dev = &memory; + int retval; + + /* other non-static parts of init */ + dev->dev = _dev; + dev->mach = _dev->platform_data; + + /** @todo RPFIXME check if still needed L.Joye */ + UP2OCR = UP2OCR_HXOE; + + init_timer(&dev->timer); + dev->timer.function = udc_watchdog; + dev->timer.data = (unsigned long) dev; + + device_initialize(&dev->gadget.dev); + dev->gadget.dev.parent = _dev; + dev->gadget.dev.dma_mask = _dev->dma_mask; + + the_controller = dev; + dev_set_drvdata(_dev, dev); + + udc_disable(dev); + udc_init_ep(dev); + udc_reinit(dev); + + /* irq setup after old hardware state is cleaned up */ + retval = request_irq(IRQ_USB, pxa27x_udc_irq, + IRQF_DISABLED, driver_name, dev); + if (retval != 0) { + printk(KERN_ERR "%s: can't get irq %i, err %d\n", + driver_name, IRQ_USB, retval); + return -EBUSY; + } + dev->got_irq = 1; + + create_proc_files(); + + return 0; +} + +static int __exit pxa27x_udc_remove(struct device *_dev) +{ + struct pxa27x_udc *dev = _dev->driver_data; + + if (dev->driver) + return -EBUSY; + + udc_disable(dev); + remove_proc_files(); + usb_gadget_unregister_driver(dev->driver); + + pxa27x_ep_freeall(&dev->gadget); + + if (dev->got_irq) { + free_irq(IRQ_USB, dev); + dev->got_irq = 0; + } + dev_set_drvdata(_dev, 0); + the_controller = 0; + return 0; +} + +#ifdef CONFIG_PM +static void pxa27x_udc_shutdown(struct device *_dev) +{ + struct pxa27x_udc *dev = (struct pxa27x_udc*)dev_get_drvdata(_dev); + + udc_disable(dev); +} + +static int pxa27x_udc_suspend(struct device *_dev, pm_message_t state) +{ + int i; + struct pxa27x_udc *dev = (struct pxa27x_udc*)dev_get_drvdata(_dev); + + DMSG("%s is called\n", __FUNCTION__); + + dev->udccsr0 = UDCCSR0; + for(i=1; (iep[i].assigned) { + struct pxa27x_ep *ep = &dev->ep[i]; + ep->udccsr_value = *ep->reg_udccsr; + ep->udccr_value = *ep->reg_udccr; + DMSG("EP%d, udccsr:0x%x, udccr:0x%x\n", + i, *ep->reg_udccsr, *ep->reg_udccr); + } + } + + udc_clear_mask_UDCCR(UDCCR_UDE); + pxa_set_cken(CKEN_USB, 0); + + return 0; +} + +static int pxa27x_udc_resume(struct device *_dev) +{ + int i; + struct pxa27x_udc *dev = dev_get_drvdata(_dev); + + DMSG("%s is called\n", __FUNCTION__); + UDCCSR0 = dev->udccsr0 & (UDCCSR0_FST | UDCCSR0_DME); + for (i=1; i < UDC_EP_NUM; i++) { + if (dev->ep[i].assigned) { + struct pxa27x_ep *ep = &dev->ep[i]; + *ep->reg_udccsr = ep->udccsr_value; + *ep->reg_udccr = ep->udccr_value; + DMSG("EP%d, udccsr:0x%x, udccr:0x%x\n", + i, *ep->reg_udccsr, *ep->reg_udccr); + } + } + + udc_enable(dev); + + /* OTGPH bit is set when sleep mode is entered. + * it indicates that OTG pad is retaining its state. + * Upon exit from sleep mode and before clearing OTGPH, + * Software must configure the USB OTG pad, UDC, and UHC + * to the state they were in before entering sleep mode.*/ + PSSR |= PSSR_OTGPH; + + return 0; +} +#endif + +/*-------------------------------------------------------------------------*/ + +static struct device_driver udc_driver = { + .name = "pxa2xx-udc", + .owner = THIS_MODULE, + .bus = &platform_bus_type, + .probe = pxa27x_udc_probe, + .remove = __exit_p(pxa27x_udc_remove), +#ifdef CONFIG_PM + .shutdown = pxa27x_udc_shutdown, + .suspend = pxa27x_udc_suspend, + .resume = pxa27x_udc_resume +#endif +}; + +static int __init udc_init(void) +{ + printk(KERN_INFO "%s: version %s\n", driver_name, DRIVER_VERSION); + return driver_register(&udc_driver); +} +module_init(udc_init); + +static void __exit udc_exit(void) +{ + driver_unregister(&udc_driver); +} +module_exit(udc_exit); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR("Frank Becker, Robert Schwebel, David Brownell"); +MODULE_LICENSE("GPL"); diff -urN linux-2.6.30.4-orig/drivers/usb/gadget/pxa27x_udc_sysgo.h linux-2.6.30.4/drivers/usb/gadget/pxa27x_udc_sysgo.h --- linux-2.6.30.4-orig/drivers/usb/gadget/pxa27x_udc_sysgo.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/drivers/usb/gadget/pxa27x_udc_sysgo.h 2009-08-05 16:11:13.000000000 +0200 @@ -0,0 +1,716 @@ +/* + * linux/drivers/usb/gadget/pxa27x_udc.h + * Intel PXA27x on-chip full speed USB device controller + * + * Copyright (C) 2003 Robert Schwebel , Pengutronix + * Copyright (C) 2003 David Brownell + * Copyright (C) 2004 Intel Corporation + * + * 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 + */ + +#ifndef __LINUX_USB_GADGET_PXA27X_H +#define __LINUX_USB_GADGET_PXA27X_H + +#include + + + + +/* + * USB Device Controller + * PXA25x and PXA27x USB device controller registers are different. + */ +#if defined(CONFIG_PXA25x) + +#define UDC_RES1 __REG(0x40600004) /* UDC Undocumented - Reserved1 */ +#define UDC_RES2 __REG(0x40600008) /* UDC Undocumented - Reserved2 */ +#define UDC_RES3 __REG(0x4060000C) /* UDC Undocumented - Reserved3 */ + +#define UDCCR __REG(0x40600000) /* UDC Control Register */ +#define UDCCR_UDE (1 << 0) /* UDC enable */ +#define UDCCR_UDA (1 << 1) /* UDC active */ +#define UDCCR_RSM (1 << 2) /* Device resume */ +#define UDCCR_RESIR (1 << 3) /* Resume interrupt request */ +#define UDCCR_SUSIR (1 << 4) /* Suspend interrupt request */ +#define UDCCR_SRM (1 << 5) /* Suspend/resume interrupt mask */ +#define UDCCR_RSTIR (1 << 6) /* Reset interrupt request */ +#define UDCCR_REM (1 << 7) /* Reset interrupt mask */ + +#define UDCCS0 __REG(0x40600010) /* UDC Endpoint 0 Control/Status Register */ +#define UDCCS0_OPR (1 << 0) /* OUT packet ready */ +#define UDCCS0_IPR (1 << 1) /* IN packet ready */ +#define UDCCS0_FTF (1 << 2) /* Flush Tx FIFO */ +#define UDCCS0_DRWF (1 << 3) /* Device remote wakeup feature */ +#define UDCCS0_SST (1 << 4) /* Sent stall */ +#define UDCCS0_FST (1 << 5) /* Force stall */ +#define UDCCS0_RNE (1 << 6) /* Receive FIFO no empty */ +#define UDCCS0_SA (1 << 7) /* Setup active */ + +/* Bulk IN - Endpoint 1,6,11 */ +#define UDCCS1 __REG(0x40600014) /* UDC Endpoint 1 (IN) Control/Status Register */ +#define UDCCS6 __REG(0x40600028) /* UDC Endpoint 6 (IN) Control/Status Register */ +#define UDCCS11 __REG(0x4060003C) /* UDC Endpoint 11 (IN) Control/Status Register */ + +#define UDCCS_BI_TFS (1 << 0) /* Transmit FIFO service */ +#define UDCCS_BI_TPC (1 << 1) /* Transmit packet complete */ +#define UDCCS_BI_FTF (1 << 2) /* Flush Tx FIFO */ +#define UDCCS_BI_TUR (1 << 3) /* Transmit FIFO underrun */ +#define UDCCS_BI_SST (1 << 4) /* Sent stall */ +#define UDCCS_BI_FST (1 << 5) /* Force stall */ +#define UDCCS_BI_TSP (1 << 7) /* Transmit short packet */ + +/* Bulk OUT - Endpoint 2,7,12 */ +#define UDCCS2 __REG(0x40600018) /* UDC Endpoint 2 (OUT) Control/Status Register */ +#define UDCCS7 __REG(0x4060002C) /* UDC Endpoint 7 (OUT) Control/Status Register */ +#define UDCCS12 __REG(0x40600040) /* UDC Endpoint 12 (OUT) Control/Status Register */ + +#define UDCCS_BO_RFS (1 << 0) /* Receive FIFO service */ +#define UDCCS_BO_RPC (1 << 1) /* Receive packet complete */ +#define UDCCS_BO_DME (1 << 3) /* DMA enable */ +#define UDCCS_BO_SST (1 << 4) /* Sent stall */ +#define UDCCS_BO_FST (1 << 5) /* Force stall */ +#define UDCCS_BO_RNE (1 << 6) /* Receive FIFO not empty */ +#define UDCCS_BO_RSP (1 << 7) /* Receive short packet */ + +/* Isochronous IN - Endpoint 3,8,13 */ +#define UDCCS3 __REG(0x4060001C) /* UDC Endpoint 3 (IN) Control/Status Register */ +#define UDCCS8 __REG(0x40600030) /* UDC Endpoint 8 (IN) Control/Status Register */ +#define UDCCS13 __REG(0x40600044) /* UDC Endpoint 13 (IN) Control/Status Register */ + +#define UDCCS_II_TFS (1 << 0) /* Transmit FIFO service */ +#define UDCCS_II_TPC (1 << 1) /* Transmit packet complete */ +#define UDCCS_II_FTF (1 << 2) /* Flush Tx FIFO */ +#define UDCCS_II_TUR (1 << 3) /* Transmit FIFO underrun */ +#define UDCCS_II_TSP (1 << 7) /* Transmit short packet */ + +/* Isochronous OUT - Endpoint 4,9,14 */ +#define UDCCS4 __REG(0x40600020) /* UDC Endpoint 4 (OUT) Control/Status Register */ +#define UDCCS9 __REG(0x40600034) /* UDC Endpoint 9 (OUT) Control/Status Register */ +#define UDCCS14 __REG(0x40600048) /* UDC Endpoint 14 (OUT) Control/Status Register */ + +#define UDCCS_IO_RFS (1 << 0) /* Receive FIFO service */ +#define UDCCS_IO_RPC (1 << 1) /* Receive packet complete */ +#define UDCCS_IO_ROF (1 << 2) /* Receive overflow */ +#define UDCCS_IO_DME (1 << 3) /* DMA enable */ +#define UDCCS_IO_RNE (1 << 6) /* Receive FIFO not empty */ +#define UDCCS_IO_RSP (1 << 7) /* Receive short packet */ + +/* Interrupt IN - Endpoint 5,10,15 */ +#define UDCCS5 __REG(0x40600024) /* UDC Endpoint 5 (Interrupt) Control/Status Register */ +#define UDCCS10 __REG(0x40600038) /* UDC Endpoint 10 (Interrupt) Control/Status Register */ +#define UDCCS15 __REG(0x4060004C) /* UDC Endpoint 15 (Interrupt) Control/Status Register */ + +#define UDCCS_INT_TFS (1 << 0) /* Transmit FIFO service */ +#define UDCCS_INT_TPC (1 << 1) /* Transmit packet complete */ +#define UDCCS_INT_FTF (1 << 2) /* Flush Tx FIFO */ +#define UDCCS_INT_TUR (1 << 3) /* Transmit FIFO underrun */ +#define UDCCS_INT_SST (1 << 4) /* Sent stall */ +#define UDCCS_INT_FST (1 << 5) /* Force stall */ +#define UDCCS_INT_TSP (1 << 7) /* Transmit short packet */ + +#define UFNRH __REG(0x40600060) /* UDC Frame Number Register High */ +#define UFNRL __REG(0x40600064) /* UDC Frame Number Register Low */ +#define UBCR2 __REG(0x40600068) /* UDC Byte Count Reg 2 */ +#define UBCR4 __REG(0x4060006c) /* UDC Byte Count Reg 4 */ +#define UBCR7 __REG(0x40600070) /* UDC Byte Count Reg 7 */ +#define UBCR9 __REG(0x40600074) /* UDC Byte Count Reg 9 */ +#define UBCR12 __REG(0x40600078) /* UDC Byte Count Reg 12 */ +#define UBCR14 __REG(0x4060007c) /* UDC Byte Count Reg 14 */ +#define UDDR0 __REG(0x40600080) /* UDC Endpoint 0 Data Register */ +#define UDDR1 __REG(0x40600100) /* UDC Endpoint 1 Data Register */ +#define UDDR2 __REG(0x40600180) /* UDC Endpoint 2 Data Register */ +#define UDDR3 __REG(0x40600200) /* UDC Endpoint 3 Data Register */ +#define UDDR4 __REG(0x40600400) /* UDC Endpoint 4 Data Register */ +#define UDDR5 __REG(0x406000A0) /* UDC Endpoint 5 Data Register */ +#define UDDR6 __REG(0x40600600) /* UDC Endpoint 6 Data Register */ +#define UDDR7 __REG(0x40600680) /* UDC Endpoint 7 Data Register */ +#define UDDR8 __REG(0x40600700) /* UDC Endpoint 8 Data Register */ +#define UDDR9 __REG(0x40600900) /* UDC Endpoint 9 Data Register */ +#define UDDR10 __REG(0x406000C0) /* UDC Endpoint 10 Data Register */ +#define UDDR11 __REG(0x40600B00) /* UDC Endpoint 11 Data Register */ +#define UDDR12 __REG(0x40600B80) /* UDC Endpoint 12 Data Register */ +#define UDDR13 __REG(0x40600C00) /* UDC Endpoint 13 Data Register */ +#define UDDR14 __REG(0x40600E00) /* UDC Endpoint 14 Data Register */ +#define UDDR15 __REG(0x406000E0) /* UDC Endpoint 15 Data Register */ + +#define UICR0 __REG(0x40600050) /* UDC Interrupt Control Register 0 */ + +#define UICR0_IM0 (1 << 0) /* Interrupt mask ep 0 */ +#define UICR0_IM1 (1 << 1) /* Interrupt mask ep 1 */ +#define UICR0_IM2 (1 << 2) /* Interrupt mask ep 2 */ +#define UICR0_IM3 (1 << 3) /* Interrupt mask ep 3 */ +#define UICR0_IM4 (1 << 4) /* Interrupt mask ep 4 */ +#define UICR0_IM5 (1 << 5) /* Interrupt mask ep 5 */ +#define UICR0_IM6 (1 << 6) /* Interrupt mask ep 6 */ +#define UICR0_IM7 (1 << 7) /* Interrupt mask ep 7 */ + +#define UICR1 __REG(0x40600054) /* UDC Interrupt Control Register 1 */ + +#define UICR1_IM8 (1 << 0) /* Interrupt mask ep 8 */ +#define UICR1_IM9 (1 << 1) /* Interrupt mask ep 9 */ +#define UICR1_IM10 (1 << 2) /* Interrupt mask ep 10 */ +#define UICR1_IM11 (1 << 3) /* Interrupt mask ep 11 */ +#define UICR1_IM12 (1 << 4) /* Interrupt mask ep 12 */ +#define UICR1_IM13 (1 << 5) /* Interrupt mask ep 13 */ +#define UICR1_IM14 (1 << 6) /* Interrupt mask ep 14 */ +#define UICR1_IM15 (1 << 7) /* Interrupt mask ep 15 */ + +#define USIR0 __REG(0x40600058) /* UDC Status Interrupt Register 0 */ + +#define USIR0_IR0 (1 << 0) /* Interrup request ep 0 */ +#define USIR0_IR1 (1 << 1) /* Interrup request ep 1 */ +#define USIR0_IR2 (1 << 2) /* Interrup request ep 2 */ +#define USIR0_IR3 (1 << 3) /* Interrup request ep 3 */ +#define USIR0_IR4 (1 << 4) /* Interrup request ep 4 */ +#define USIR0_IR5 (1 << 5) /* Interrup request ep 5 */ +#define USIR0_IR6 (1 << 6) /* Interrup request ep 6 */ +#define USIR0_IR7 (1 << 7) /* Interrup request ep 7 */ + +#define USIR1 __REG(0x4060005C) /* UDC Status Interrupt Register 1 */ + +#define USIR1_IR8 (1 << 0) /* Interrup request ep 8 */ +#define USIR1_IR9 (1 << 1) /* Interrup request ep 9 */ +#define USIR1_IR10 (1 << 2) /* Interrup request ep 10 */ +#define USIR1_IR11 (1 << 3) /* Interrup request ep 11 */ +#define USIR1_IR12 (1 << 4) /* Interrup request ep 12 */ +#define USIR1_IR13 (1 << 5) /* Interrup request ep 13 */ +#define USIR1_IR14 (1 << 6) /* Interrup request ep 14 */ +#define USIR1_IR15 (1 << 7) /* Interrup request ep 15 */ + +#elif defined(CONFIG_PXA27x) + +#define UDCCR __REG(0x40600000) /* UDC Control Register */ +#define UDCCR_OEN (1 << 31) /* On-the-Go Enable */ +#define UDCCR_AALTHNP (1 << 30) /* A-device Alternate Host Negotiation + Protocol Port Support */ +#define UDCCR_AHNP (1 << 29) /* A-device Host Negotiation Protocol + Support */ +#define UDCCR_BHNP (1 << 28) /* B-device Host Negotiation Protocol + Enable */ +#define UDCCR_DWRE (1 << 16) /* Device Remote Wake-up Enable */ +#define UDCCR_ACN (0x03 << 11) /* Active UDC configuration Number */ +#define UDCCR_ACN_S 11 +#define UDCCR_AIN (0x07 << 8) /* Active UDC interface Number */ +#define UDCCR_AIN_S 8 +#define UDCCR_AAISN (0x07 << 5) /* Active UDC Alternate Interface + Setting Number */ +#define UDCCR_AAISN_S 5 +#define UDCCR_SMAC (1 << 4) /* Switch Endpoint Memory to Active + Configuration */ +#define UDCCR_EMCE (1 << 3) /* Endpoint Memory Configuration + Error */ +#define UDCCR_UDR (1 << 2) /* UDC Resume */ +#define UDCCR_UDA (1 << 1) /* UDC Active */ +#define UDCCR_UDE (1 << 0) /* UDC Enable */ + +#define UDCICR0 __REG(0x40600004) /* UDC Interrupt Control Register0 */ +#define UDCICR1 __REG(0x40600008) /* UDC Interrupt Control Register1 */ +#define UDCICR_FIFOERR (1 << 1) /* FIFO Error interrupt for EP */ +#define UDCICR_PKTCOMPL (1 << 0) /* Packet Complete interrupt for EP */ + +#define UDC_INT_FIFOERROR (0x2) +#define UDC_INT_PACKETCMP (0x1) + +#define UDCICR_INT(n,intr) (((intr) & 0x03) << (((n) & 0x0F) * 2)) +#define UDCICR1_IECC (1 << 31) /* IntEn - Configuration Change */ +#define UDCICR1_IESOF (1 << 30) /* IntEn - Start of Frame */ +#define UDCICR1_IERU (1 << 29) /* IntEn - Resume */ +#define UDCICR1_IESU (1 << 28) /* IntEn - Suspend */ +#define UDCICR1_IERS (1 << 27) /* IntEn - Reset */ + +#define UDCISR0 __REG(0x4060000C) /* UDC Interrupt Status Register 0 */ +#define UDCISR1 __REG(0x40600010) /* UDC Interrupt Status Register 1 */ +#define UDCISR_INT(n,intr) (((intr) & 0x03) << (((n) & 0x0F) * 2)) +#define UDCISR1_IRCC (1 << 31) /* IntReq - Configuration Change */ +#define UDCISR1_IRSOF (1 << 30) /* IntReq - Start of Frame */ +#define UDCISR1_IRRU (1 << 29) /* IntReq - Resume */ +#define UDCISR1_IRSU (1 << 28) /* IntReq - Suspend */ +#define UDCISR1_IRRS (1 << 27) /* IntReq - Reset */ + +#define UDCFNR __REG(0x40600014) /* UDC Frame Number Register */ +#define UDCOTGICR __REG(0x40600018) /* UDC On-The-Go interrupt control */ +#define UDCOTGICR_IESF (1 << 24) /* OTG SET_FEATURE command recvd */ +#define UDCOTGICR_IEXR (1 << 17) /* Extra Transciever Interrupt + Rising Edge Interrupt Enable */ +#define UDCOTGICR_IEXF (1 << 16) /* Extra Transciever Interrupt + Falling Edge Interrupt Enable */ +#define UDCOTGICR_IEVV40R (1 << 9) /* OTG Vbus Valid 4.0V Rising Edge + Interrupt Enable */ +#define UDCOTGICR_IEVV40F (1 << 8) /* OTG Vbus Valid 4.0V Falling Edge + Interrupt Enable */ +#define UDCOTGICR_IEVV44R (1 << 7) /* OTG Vbus Valid 4.4V Rising Edge + Interrupt Enable */ +#define UDCOTGICR_IEVV44F (1 << 6) /* OTG Vbus Valid 4.4V Falling Edge + Interrupt Enable */ +#define UDCOTGICR_IESVR (1 << 5) /* OTG Session Valid Rising Edge + Interrupt Enable */ +#define UDCOTGICR_IESVF (1 << 4) /* OTG Session Valid Falling Edge + Interrupt Enable */ +#define UDCOTGICR_IESDR (1 << 3) /* OTG A-Device SRP Detect Rising + Edge Interrupt Enable */ +#define UDCOTGICR_IESDF (1 << 2) /* OTG A-Device SRP Detect Falling + Edge Interrupt Enable */ +#define UDCOTGICR_IEIDR (1 << 1) /* OTG ID Change Rising Edge + Interrupt Enable */ +#define UDCOTGICR_IEIDF (1 << 0) /* OTG ID Change Falling Edge + Interrupt Enable */ + +#define UP2OCR __REG(0x40600020) /* USB Port 2 Output Control register */ + +#define UP2OCR_CPVEN (1 << 0) /* Charge Pump Vbus Enable */ +#define UP2OCR_CPVPE (1 << 1) /* Charge Pump Vbus Pulse Enable */ +#define UP2OCR_DPPDE (1 << 2) /* Host Port 2 Transceiver D+ Pull Down Enable */ +#define UP2OCR_DMPDE (1 << 3) /* Host Port 2 Transceiver D- Pull Down Enable */ +#define UP2OCR_DPPUE (1 << 4) /* Host Port 2 Transceiver D+ Pull Up Enable */ +#define UP2OCR_DMPUE (1 << 5) /* Host Port 2 Transceiver D- Pull Up Enable */ +#define UP2OCR_DPPUBE (1 << 6) /* Host Port 2 Transceiver D+ Pull Up Bypass Enable */ +#define UP2OCR_DMPUBE (1 << 7) /* Host Port 2 Transceiver D- Pull Up Bypass Enable */ +#define UP2OCR_EXSP (1 << 8) /* External Transceiver Speed Control */ +#define UP2OCR_EXSUS (1 << 9) /* External Transceiver Speed Enable */ +#define UP2OCR_IDON (1 << 10) /* OTG ID Read Enable */ +#define UP2OCR_HXS (1 << 16) /* Host Port 2 Transceiver Output Select */ +#define UP2OCR_HXOE (1 << 17) /* Host Port 2 Transceiver Output Enable */ +#define UP2OCR_SEOS (1 << 24) /* Single-Ended Output Select */ + +#define UDCCSN(x) __REG2(0x40600100, (x) << 2) +#define UDCCSR0 __REG(0x40600100) /* UDC Control/Status register - Endpoint 0 */ +#define UDCCSR0_SA (1 << 7) /* Setup Active */ +#define UDCCSR0_RNE (1 << 6) /* Receive FIFO Not Empty */ +#define UDCCSR0_FST (1 << 5) /* Force Stall */ +#define UDCCSR0_SST (1 << 4) /* Sent Stall */ +#define UDCCSR0_DME (1 << 3) /* DMA Enable */ +#define UDCCSR0_FTF (1 << 2) /* Flush Transmit FIFO */ +#define UDCCSR0_IPR (1 << 1) /* IN Packet Ready */ +#define UDCCSR0_OPC (1 << 0) /* OUT Packet Complete */ + +#define UDCCSRA __REG(0x40600104) /* UDC Control/Status register - Endpoint A */ +#define UDCCSRB __REG(0x40600108) /* UDC Control/Status register - Endpoint B */ +#define UDCCSRC __REG(0x4060010C) /* UDC Control/Status register - Endpoint C */ +#define UDCCSRD __REG(0x40600110) /* UDC Control/Status register - Endpoint D */ +#define UDCCSRE __REG(0x40600114) /* UDC Control/Status register - Endpoint E */ +#define UDCCSRF __REG(0x40600118) /* UDC Control/Status register - Endpoint F */ +#define UDCCSRG __REG(0x4060011C) /* UDC Control/Status register - Endpoint G */ +#define UDCCSRH __REG(0x40600120) /* UDC Control/Status register - Endpoint H */ +#define UDCCSRI __REG(0x40600124) /* UDC Control/Status register - Endpoint I */ +#define UDCCSRJ __REG(0x40600128) /* UDC Control/Status register - Endpoint J */ +#define UDCCSRK __REG(0x4060012C) /* UDC Control/Status register - Endpoint K */ +#define UDCCSRL __REG(0x40600130) /* UDC Control/Status register - Endpoint L */ +#define UDCCSRM __REG(0x40600134) /* UDC Control/Status register - Endpoint M */ +#define UDCCSRN __REG(0x40600138) /* UDC Control/Status register - Endpoint N */ +#define UDCCSRP __REG(0x4060013C) /* UDC Control/Status register - Endpoint P */ +#define UDCCSRQ __REG(0x40600140) /* UDC Control/Status register - Endpoint Q */ +#define UDCCSRR __REG(0x40600144) /* UDC Control/Status register - Endpoint R */ +#define UDCCSRS __REG(0x40600148) /* UDC Control/Status register - Endpoint S */ +#define UDCCSRT __REG(0x4060014C) /* UDC Control/Status register - Endpoint T */ +#define UDCCSRU __REG(0x40600150) /* UDC Control/Status register - Endpoint U */ +#define UDCCSRV __REG(0x40600154) /* UDC Control/Status register - Endpoint V */ +#define UDCCSRW __REG(0x40600158) /* UDC Control/Status register - Endpoint W */ +#define UDCCSRX __REG(0x4060015C) /* UDC Control/Status register - Endpoint X */ + +#define UDCCSR_DPE (1 << 9) /* Data Packet Error */ +#define UDCCSR_FEF (1 << 8) /* Flush Endpoint FIFO */ +#define UDCCSR_SP (1 << 7) /* Short Packet Control/Status */ +#define UDCCSR_BNE (1 << 6) /* Buffer Not Empty (IN endpoints) */ +#define UDCCSR_BNF (1 << 6) /* Buffer Not Full (OUT endpoints) */ +#define UDCCSR_FST (1 << 5) /* Force STALL */ +#define UDCCSR_SST (1 << 4) /* Sent STALL */ +#define UDCCSR_DME (1 << 3) /* DMA Enable */ +#define UDCCSR_TRN (1 << 2) /* Tx/Rx NAK */ +#define UDCCSR_PC (1 << 1) /* Packet Complete */ +#define UDCCSR_FS (1 << 0) /* FIFO needs service */ + +#define UDCBCN(x) __REG2(0x40600200, (x)<<2) +#define UDCBCR0 __REG(0x40600200) /* Byte Count Register - EP0 */ +#define UDCBCRA __REG(0x40600204) /* Byte Count Register - EPA */ +#define UDCBCRB __REG(0x40600208) /* Byte Count Register - EPB */ +#define UDCBCRC __REG(0x4060020C) /* Byte Count Register - EPC */ +#define UDCBCRD __REG(0x40600210) /* Byte Count Register - EPD */ +#define UDCBCRE __REG(0x40600214) /* Byte Count Register - EPE */ +#define UDCBCRF __REG(0x40600218) /* Byte Count Register - EPF */ +#define UDCBCRG __REG(0x4060021C) /* Byte Count Register - EPG */ +#define UDCBCRH __REG(0x40600220) /* Byte Count Register - EPH */ +#define UDCBCRI __REG(0x40600224) /* Byte Count Register - EPI */ +#define UDCBCRJ __REG(0x40600228) /* Byte Count Register - EPJ */ +#define UDCBCRK __REG(0x4060022C) /* Byte Count Register - EPK */ +#define UDCBCRL __REG(0x40600230) /* Byte Count Register - EPL */ +#define UDCBCRM __REG(0x40600234) /* Byte Count Register - EPM */ +#define UDCBCRN __REG(0x40600238) /* Byte Count Register - EPN */ +#define UDCBCRP __REG(0x4060023C) /* Byte Count Register - EPP */ +#define UDCBCRQ __REG(0x40600240) /* Byte Count Register - EPQ */ +#define UDCBCRR __REG(0x40600244) /* Byte Count Register - EPR */ +#define UDCBCRS __REG(0x40600248) /* Byte Count Register - EPS */ +#define UDCBCRT __REG(0x4060024C) /* Byte Count Register - EPT */ +#define UDCBCRU __REG(0x40600250) /* Byte Count Register - EPU */ +#define UDCBCRV __REG(0x40600254) /* Byte Count Register - EPV */ +#define UDCBCRW __REG(0x40600258) /* Byte Count Register - EPW */ +#define UDCBCRX __REG(0x4060025C) /* Byte Count Register - EPX */ + +#define UDCDN(x) __REG2(0x40600300, (x)<<2) +#define PHYS_UDCDN(x) (0x40600300 + ((x)<<2)) +#define PUDCDN(x) (volatile u32 *)(io_p2v(PHYS_UDCDN((x)))) +#define UDCDR0 __REG(0x40600300) /* Data Register - EP0 */ +#define UDCDRA __REG(0x40600304) /* Data Register - EPA */ +#define UDCDRB __REG(0x40600308) /* Data Register - EPB */ +#define UDCDRC __REG(0x4060030C) /* Data Register - EPC */ +#define UDCDRD __REG(0x40600310) /* Data Register - EPD */ +#define UDCDRE __REG(0x40600314) /* Data Register - EPE */ +#define UDCDRF __REG(0x40600318) /* Data Register - EPF */ +#define UDCDRG __REG(0x4060031C) /* Data Register - EPG */ +#define UDCDRH __REG(0x40600320) /* Data Register - EPH */ +#define UDCDRI __REG(0x40600324) /* Data Register - EPI */ +#define UDCDRJ __REG(0x40600328) /* Data Register - EPJ */ +#define UDCDRK __REG(0x4060032C) /* Data Register - EPK */ +#define UDCDRL __REG(0x40600330) /* Data Register - EPL */ +#define UDCDRM __REG(0x40600334) /* Data Register - EPM */ +#define UDCDRN __REG(0x40600338) /* Data Register - EPN */ +#define UDCDRP __REG(0x4060033C) /* Data Register - EPP */ +#define UDCDRQ __REG(0x40600340) /* Data Register - EPQ */ +#define UDCDRR __REG(0x40600344) /* Data Register - EPR */ +#define UDCDRS __REG(0x40600348) /* Data Register - EPS */ +#define UDCDRT __REG(0x4060034C) /* Data Register - EPT */ +#define UDCDRU __REG(0x40600350) /* Data Register - EPU */ +#define UDCDRV __REG(0x40600354) /* Data Register - EPV */ +#define UDCDRW __REG(0x40600358) /* Data Register - EPW */ +#define UDCDRX __REG(0x4060035C) /* Data Register - EPX */ + +#define UDCCN(x) __REG2(0x40600400, (x)<<2) +#define UDCCRA __REG(0x40600404) /* Configuration register EPA */ +#define UDCCRB __REG(0x40600408) /* Configuration register EPB */ +#define UDCCRC __REG(0x4060040C) /* Configuration register EPC */ +#define UDCCRD __REG(0x40600410) /* Configuration register EPD */ +#define UDCCRE __REG(0x40600414) /* Configuration register EPE */ +#define UDCCRF __REG(0x40600418) /* Configuration register EPF */ +#define UDCCRG __REG(0x4060041C) /* Configuration register EPG */ +#define UDCCRH __REG(0x40600420) /* Configuration register EPH */ +#define UDCCRI __REG(0x40600424) /* Configuration register EPI */ +#define UDCCRJ __REG(0x40600428) /* Configuration register EPJ */ +#define UDCCRK __REG(0x4060042C) /* Configuration register EPK */ +#define UDCCRL __REG(0x40600430) /* Configuration register EPL */ +#define UDCCRM __REG(0x40600434) /* Configuration register EPM */ +#define UDCCRN __REG(0x40600438) /* Configuration register EPN */ +#define UDCCRP __REG(0x4060043C) /* Configuration register EPP */ +#define UDCCRQ __REG(0x40600440) /* Configuration register EPQ */ +#define UDCCRR __REG(0x40600444) /* Configuration register EPR */ +#define UDCCRS __REG(0x40600448) /* Configuration register EPS */ +#define UDCCRT __REG(0x4060044C) /* Configuration register EPT */ +#define UDCCRU __REG(0x40600450) /* Configuration register EPU */ +#define UDCCRV __REG(0x40600454) /* Configuration register EPV */ +#define UDCCRW __REG(0x40600458) /* Configuration register EPW */ +#define UDCCRX __REG(0x4060045C) /* Configuration register EPX */ + +#define UDCCONR_CN (0x03 << 25) /* Configuration Number */ +#define UDCCONR_CN_S (25) +#define UDCCONR_IN (0x07 << 22) /* Interface Number */ +#define UDCCONR_IN_S (22) +#define UDCCONR_AISN (0x07 << 19) /* Alternate Interface Number */ +#define UDCCONR_AISN_S (19) +#define UDCCONR_EN (0x0f << 15) /* Endpoint Number */ +#define UDCCONR_EN_S (15) +#define UDCCONR_ET (0x03 << 13) /* Endpoint Type: */ +#define UDCCONR_ET_S (13) +#define UDCCONR_ET_INT (0x03 << 13) /* Interrupt */ +#define UDCCONR_ET_BULK (0x02 << 13) /* Bulk */ +#define UDCCONR_ET_ISO (0x01 << 13) /* Isochronous */ +#define UDCCONR_ET_NU (0x00 << 13) /* Not used */ +#define UDCCONR_ED (1 << 12) /* Endpoint Direction */ +#define UDCCONR_MPS (0x3ff << 2) /* Maximum Packet Size */ +#define UDCCONR_MPS_S (2) +#define UDCCONR_DE (1 << 1) /* Double Buffering Enable */ +#define UDCCONR_EE (1 << 0) /* Endpoint Enable */ + + +#define UDC_INT_FIFOERROR (0x2) +#define UDC_INT_PACKETCMP (0x1) + +#define UDC_FNR_MASK (0x7ff) + +#define UDCCSR_WR_MASK (UDCCSR_DME|UDCCSR_FST) +#define UDC_BCR_MASK (0x3ff) +#endif + + + + +struct pxa27x_udc; + +struct pxa27x_ep { + struct pxa27x_udc *dev; + struct usb_ep *usb_ep; + const struct usb_endpoint_descriptor *desc; + + struct list_head queue; + unsigned long pio_irqs; + unsigned long dma_irqs; + + unsigned pxa_ep_num; + int dma; + unsigned fifo_size; + unsigned ep_type; + + unsigned stopped : 1; + unsigned dma_con : 1; + unsigned dir_in : 1; + unsigned assigned : 1; + + unsigned ep_num; + unsigned config; + unsigned interface; + unsigned aisn; + /* UDCCSR = UDC Control/Status Register for this EP + * UBCR = UDC Byte Count Remaining (contents of OUT fifo) + * UDCDR = UDC Endpoint Data Register (the fifo) + * UDCCR = UDC Endpoint Configuration Registers + * DRCM = DMA Request Channel Map + */ + volatile u32 *reg_udccsr; + volatile u32 *reg_udcbcr; + volatile u32 *reg_udcdr; + volatile u32 *reg_udccr; +#ifdef USE_DMA + volatile u32 *reg_drcmr; +#define drcmr(n) .reg_drcmr = & DRCMR ## n , +#else +#define drcmr(n) +#endif + +#ifdef CONFIG_PM + unsigned udccsr_value; + unsigned udccr_value; +#endif +}; + +struct pxa27x_virt_ep { + struct usb_ep usb_ep; + const struct usb_endpoint_descriptor *desc; + struct pxa27x_ep *pxa_ep; +}; + +struct pxa27x_request { + struct usb_request req; + struct list_head queue; +}; + +enum ep0_state { + EP0_IDLE, + EP0_IN_DATA_PHASE, + EP0_OUT_DATA_PHASE, +// EP0_END_XFER, + EP0_STALL, + EP0_NO_ACTION +}; + +#define EP0_FIFO_SIZE ((unsigned)16) +#define BULK_FIFO_SIZE ((unsigned)64) +#define ISO_FIFO_SIZE ((unsigned)256) +#define INT_FIFO_SIZE ((unsigned)8) + +struct udc_stats { + struct ep0stats { + unsigned long ops; + unsigned long bytes; + } read, write; + unsigned long irqs; +}; + +#define UDC_EP_NUM 24 + + +struct pxa27x_udc { + struct usb_gadget gadget; + struct usb_gadget_driver *driver; + + enum ep0_state ep0state; + struct udc_stats stats; + unsigned got_irq : 1, + has_cfr : 1, + req_pending : 1, + req_std : 1, + req_config : 1; + +#define start_watchdog(dev) mod_timer(&dev->timer, jiffies + (HZ/200)) + struct timer_list timer; + + struct device *dev; + struct pxa2xx_udc_mach_info *mach; + u64 dma_mask; + struct pxa27x_virt_ep virt_ep0; + struct pxa27x_ep ep[UDC_EP_NUM]; + unsigned int ep_num; + + unsigned configuration, + interface, + alternate; +#ifdef CONFIG_PM + unsigned udccsr0; +#endif +}; + +static struct pxa27x_udc *the_controller; + +#if 0 +/*-------------------------------------------------------------------------*/ + + +/* one GPIO should be used to detect host disconnect */ +static inline int is_usb_connected(void) +{ + if (!the_controller->mach->udc_is_connected) + return 1; + return the_controller->mach->udc_is_connected(); +} + +/* one GPIO should force the host to see this device (or not) */ +static inline void make_usb_disappear(void) +{ + if (!the_controller->mach->udc_command) + return; + the_controller->mach->udc_command(PXA27X_UDC_CMD_DISCONNECT); +} + +static inline void let_usb_appear(void) +{ + if (!the_controller->mach->udc_command) + return; + the_controller->mach->udc_command(PXA2XX_UDC_CMD_CONNECT); +} +#endif + +/*-------------------------------------------------------------------------*/ + +/* + * Debugging support vanishes in non-debug builds. DBG_NORMAL should be + * mostly silent during normal use/testing, with no timing side-effects. + */ +#define DBG_NORMAL 1 /* error paths, device state transitions */ +#define DBG_VERBOSE 2 /* add some success path trace info */ +#define DBG_NOISY 3 /* ... even more: request level */ +#define DBG_VERY_NOISY 4 /* ... even more: packet level */ + +#ifdef DEBUG +static const char *state_name[] = { + "EP0_IDLE", + "EP0_IN_DATA_PHASE", "EP0_OUT_DATA_PHASE", + "EP0_END_XFER", "EP0_STALL" +}; + +#define DMSG(stuff...) printk(KERN_ERR "udc: " stuff) + +#ifdef VERBOSE +# define UDC_DEBUG DBG_VERBOSE +#else +# define UDC_DEBUG DBG_NORMAL +#endif + +static void __attribute__ ((__unused__)) +dump_udccr(const char *label) +{ + u32 udccr = UDCCR; + DMSG("%s 0x%08x =%s%s%s%s%s%s%s%s%s%s, con=%d,inter=%d,altinter=%d\n", + label, udccr, + (udccr & UDCCR_OEN) ? " oen":"", + (udccr & UDCCR_AALTHNP) ? " aalthnp":"", + (udccr & UDCCR_AHNP) ? " rem" : "", + (udccr & UDCCR_BHNP) ? " rstir" : "", + (udccr & UDCCR_DWRE) ? " dwre" : "", + (udccr & UDCCR_SMAC) ? " smac" : "", + (udccr & UDCCR_EMCE) ? " emce" : "", + (udccr & UDCCR_UDR) ? " udr" : "", + (udccr & UDCCR_UDA) ? " uda" : "", + (udccr & UDCCR_UDE) ? " ude" : "", + (udccr & UDCCR_ACN) >> UDCCR_ACN_S, + (udccr & UDCCR_AIN) >> UDCCR_AIN_S, + (udccr & UDCCR_AAISN)>> UDCCR_AAISN_S ); +} + +static void __attribute__ ((__unused__)) +dump_udccsr0(const char *label) +{ + u32 udccsr0 = UDCCSR0; + + DMSG("%s %s 0x%08x =%s%s%s%s%s%s%s\n", + label, state_name[the_controller->ep0state], udccsr0, + (udccsr0 & UDCCSR0_SA) ? " sa" : "", + (udccsr0 & UDCCSR0_RNE) ? " rne" : "", + (udccsr0 & UDCCSR0_FST) ? " fst" : "", + (udccsr0 & UDCCSR0_SST) ? " sst" : "", + (udccsr0 & UDCCSR0_DME) ? " dme" : "", + (udccsr0 & UDCCSR0_IPR) ? " ipr" : "", + (udccsr0 & UDCCSR0_OPC) ? " opr" : ""); +} + +static void __attribute__ ((__unused__)) +dump_state(struct pxa27x_udc *dev) +{ + unsigned i; + + DMSG("%s, udcicr %02X.%02X, udcsir %02X.%02x, udcfnr %02X\n", + state_name[dev->ep0state], + UDCICR1, UDCICR0, UDCISR1, UDCISR0, UDCFNR); + dump_udccr("udccr"); + + if (!dev->driver) { + DMSG("no gadget driver bound\n"); + return; + } else + DMSG("ep0 driver '%s'\n", dev->driver->driver.name); + + + dump_udccsr0 ("udccsr0"); + DMSG("ep0 IN %lu/%lu, OUT %lu/%lu\n", + dev->stats.write.bytes, dev->stats.write.ops, + dev->stats.read.bytes, dev->stats.read.ops); + + for (i = 1; i < UDC_EP_NUM; i++) { + if (dev->ep[i].assigned) + DMSG ("udccs%d = %02x\n", i, *dev->ep->reg_udccsr); + } +} + +#if 0 +static void dump_regs(u8 ep) +{ + DMSG("EP:%d UDCCSR:0x%08x UDCBCR:0x%08x\n UDCCR:0x%08x\n", + ep,UDCCSN(ep), UDCBCN(ep), UDCCN(ep)); +} +static void dump_req (struct pxa27x_request *req) +{ + struct usb_request *r = &req->req; + + DMSG("%s: buf:0x%08x length:%d dma:0x%08x actual:%d\n", + __FUNCTION__, (unsigned)r->buf, r->length, + r->dma, r->actual); +} +#endif + +#else + +#define DMSG(stuff...) do{}while(0) + +#define dump_udccr(x) do{}while(0) +#define dump_udccsr0(x) do{}while(0) +#define dump_state(x) do{}while(0) + +#define UDC_DEBUG ((unsigned)4) + +#endif + +#define DBG(lvl, stuff...) do{if ((lvl) <= UDC_DEBUG) DMSG(stuff);}while(0) + +#define WARN(stuff...) printk(KERN_WARNING "udc: " stuff) +#define INFO(stuff...) printk(KERN_INFO "udc: " stuff) + + +#endif /* __LINUX_USB_GADGET_PXA27X_H */ diff -urN linux-2.6.30.4-orig/include/linux/usb/isp1760.h linux-2.6.30.4/include/linux/usb/isp1760.h --- linux-2.6.30.4-orig/include/linux/usb/isp1760.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.30.4/include/linux/usb/isp1760.h 2009-08-05 16:11:14.000000000 +0200 @@ -0,0 +1,18 @@ +/* + * board initialization should put one of these into dev->platform_data + * and place the isp1760 onto platform_bus named "isp1760-hcd". + */ + +#ifndef __LINUX_USB_ISP1760_H +#define __LINUX_USB_ISP1760_H + +struct isp1760_platform_data { + unsigned is_isp1761:1; /* Chip is ISP1761 */ + unsigned bus_width_16:1; /* 16/32-bit data bus width */ + unsigned port1_otg:1; /* Port 1 supports OTG */ + unsigned analog_oc:1; /* Analog overcurrent */ + unsigned dack_polarity_high:1; /* DACK active high */ + unsigned dreq_polarity_high:1; /* DREQ active high */ +}; + +#endif /* __LINUX_USB_ISP1760_H */