summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJamie Lenehan <lenehan@twibble.org>2006-06-28 01:40:03 +0000
committerOpenEmbedded Project <openembedded-devel@lists.openembedded.org>2006-06-28 01:40:03 +0000
commita4ec0922c99c486493b1a5bb224f315ac7ab9a26 (patch)
tree9b5d4dfac23ce267de959ddc026177773db8144d
parentd0b038d42a9b6cc23f98e974ef4b7e4397073dfd (diff)
linux/linux-titan-sh4-2.6.16: Add a 2.6.16 kernel for the sh4 based "titan"
board. This is the only sh4 compatible kernel in OE.
-rw-r--r--packages/linux/linux-titan-sh4-2.6.16/.mtn2git_empty0
-rw-r--r--packages/linux/linux-titan-sh4-2.6.16/titan-config1468
-rw-r--r--packages/linux/linux-titan-sh4-2.6.16/titan-flash.patch3153
-rw-r--r--packages/linux/linux-titan-sh4_2.6.16.bb49
4 files changed, 4670 insertions, 0 deletions
diff --git a/packages/linux/linux-titan-sh4-2.6.16/.mtn2git_empty b/packages/linux/linux-titan-sh4-2.6.16/.mtn2git_empty
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/packages/linux/linux-titan-sh4-2.6.16/.mtn2git_empty
diff --git a/packages/linux/linux-titan-sh4-2.6.16/titan-config b/packages/linux/linux-titan-sh4-2.6.16/titan-config
new file mode 100644
index 0000000000..4b74c91411
--- /dev/null
+++ b/packages/linux/linux-titan-sh4-2.6.16/titan-config
@@ -0,0 +1,1468 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.14-sh
+# Sat Nov 12 22:58:44 2005
+#
+CONFIG_SUPERH=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# System type
+#
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+# CONFIG_SH_STB1_HARP is not set
+# CONFIG_SH_STB1_OVERDRIVE is not set
+# CONFIG_SH_HP6XX is not set
+# CONFIG_SH_CQREEK is not set
+# CONFIG_SH_DMIDA is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_CAT68701 is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_SH2000 is not set
+# CONFIG_SH_ADX is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_LANDISK is not set
+CONFIG_SH_TITAN=y
+# CONFIG_SH_UNKNOWN is not set
+
+#
+# Processor selection
+#
+CONFIG_CPU_SH4=y
+
+#
+# SH-2 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+
+#
+# SH-3 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+
+#
+# SH-4 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+CONFIG_CPU_SUBTYPE_SH7751=y
+CONFIG_CPU_SUBTYPE_SH7751R=y
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+
+#
+# ST40 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+
+#
+# SH-4A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+
+#
+# Memory management options
+#
+CONFIG_MMU=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+CONFIG_MEMORY_START=0x08030000
+CONFIG_MEMORY_SIZE=0x7fd0000
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SH_RTC=y
+CONFIG_SH_FPU=y
+# CONFIG_SH_STORE_QUEUES is not set
+
+#
+# Timer support
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_PCLK_FREQ_BOOL=y
+CONFIG_SH_PCLK_FREQ=30000000
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+CONFIG_SH_DMA=y
+CONFIG_NR_ONCHIP_DMA_CHANNELS=8
+# CONFIG_NR_DMA_CHANNELS_BOOL is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+
+#
+# Kernel features
+#
+# CONFIG_KEXEC is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_SMP is not set
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x009e0000
+# CONFIG_UBC_WAKEUP is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttySC1,38400N81 root=/dev/nfs ip=:::::eth1:autoconf"
+
+#
+# Bus options
+#
+CONFIG_PCI=y
+CONFIG_SH_PCIDMA_NONCOHERENT=y
+CONFIG_PCI_AUTO=y
+CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+CONFIG_HOTPLUG_PCI=y
+# CONFIG_HOTPLUG_PCI_FAKE is not set
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+# CONFIG_HOTPLUG_PCI_SHPC is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+# CONFIG_IP_ROUTE_FWMARK is not set
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_MULTIPATH_CACHED=y
+CONFIG_IP_ROUTE_MULTIPATH_RR=m
+CONFIG_IP_ROUTE_MULTIPATH_RANDOM=m
+CONFIG_IP_ROUTE_MULTIPATH_WRANDOM=m
+CONFIG_IP_ROUTE_MULTIPATH_DRR=m
+# CONFIG_IP_ROUTE_VERBOSE is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=y
+CONFIG_NET_IPGRE=y
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=y
+CONFIG_IPV6_PRIVACY=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_INET6_TUNNEL=y
+CONFIG_IPV6_TUNNEL=y
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CONNTRACK_EVENTS=y
+CONFIG_IP_NF_CONNTRACK_NETLINK=m
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_NETBIOS_NS=m
+CONFIG_IP_NF_TFTP=m
+# CONFIG_IP_NF_AMANDA is not set
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_OWNER=m
+# CONFIG_IP_NF_MATCH_PHYSDEV is not set
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+# CONFIG_IP_NF_MATCH_SCTP is not set
+# CONFIG_IP_NF_MATCH_DCCP is not set
+CONFIG_IP_NF_MATCH_COMMENT=m
+CONFIG_IP_NF_MATCH_CONNMARK=m
+CONFIG_IP_NF_MATCH_CONNBYTES=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_MATCH_STRING=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_TARGET_NFQUEUE=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_MARK=m
+CONFIG_IP_NF_TARGET_CLASSIFY=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CONNMARK=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_LIMIT=m
+CONFIG_IP6_NF_MATCH_MAC=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_MULTIPORT=m
+CONFIG_IP6_NF_MATCH_OWNER=m
+CONFIG_IP6_NF_MATCH_MARK=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AHESP=m
+CONFIG_IP6_NF_MATCH_LENGTH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+# CONFIG_IP6_NF_MATCH_PHYSDEV is not set
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_TARGET_NFQUEUE=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_MARK=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# Bridge: Netfilter Configuration
+#
+# CONFIG_BRIDGE_NF_EBTABLES is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=y
+CONFIG_VLAN_8021Q=y
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CLK_JIFFIES=y
+# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
+# CONFIG_NET_SCH_CLK_CPU is not set
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_QOS=y
+CONFIG_NET_ESTIMATOR=y
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_PERF=y
+CONFIG_NET_CLS_IND=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_PEDIT=m
+# CONFIG_NET_ACT_SIMP is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_IEEE80211=y
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=y
+CONFIG_IEEE80211_CRYPT_CCMP=y
+CONFIG_IEEE80211_CRYPT_TKIP=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=m
+CONFIG_MTD_DEBUG=y
+CONFIG_MTD_DEBUG_VERBOSE=0
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_PARTITIONS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLOCK=m
+# CONFIG_MTD_BLOCK_RO is not set
+CONFIG_FTL=m
+CONFIG_NFTL=m
+# CONFIG_NFTL_RW is not set
+CONFIG_INFTL=m
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_GEN_PROBE=m
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_SOLUTIONENGINE is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_NAND_IDS=m
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+CONFIG_BLK_SSFDC=y
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=m
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA24XX is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=m
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_STNIC is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NE2000 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+CONFIG_8139TOO=y
+# CONFIG_8139TOO_PIO is not set
+CONFIG_8139TOO_TUNE_TWISTER=y
+# CONFIG_8139TOO_8129 is not set
+CONFIG_8139_OLD_RX_RESET=y
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+# CONFIG_IPW2100 is not set
+# CONFIG_IPW2200 is not set
+# CONFIG_HERMES is not set
+# CONFIG_ATMEL is not set
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+CONFIG_PRISM54=m
+# CONFIG_HOSTAP is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPPOE=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+# CONFIG_SLIP_MODE_SLIP6 is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_SH_WDT=m
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_BLUETOOTH_TTY=m
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_ZD1201 is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRPRIME is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_CP2101 is not set
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+# CONFIG_USB_SERIAL_FTDI_SIO is not set
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+CONFIG_USB_SERIAL_PL2303=m
+# CONFIG_USB_SERIAL_HP4X is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_TI is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_XFS_FS=m
+CONFIG_XFS_EXPORT=y
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_SECURITY is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=m
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=m
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_SH_STANDARD_BIOS is not set
+CONFIG_EARLY_SCIF_CONSOLE=y
+# CONFIG_EARLY_PRINTK is not set
+# CONFIG_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
diff --git a/packages/linux/linux-titan-sh4-2.6.16/titan-flash.patch b/packages/linux/linux-titan-sh4-2.6.16/titan-flash.patch
new file mode 100644
index 0000000000..5a68c4ebed
--- /dev/null
+++ b/packages/linux/linux-titan-sh4-2.6.16/titan-flash.patch
@@ -0,0 +1,3153 @@
+
+Add the driver for onboard flash.
+The quality of this driver means that it has not been included in the
+upstream CVS.
+This implements the block device translation layer to match what the
+onboard firmware implements.
+
+diff -durN -X ../diff.ignore linux/drivers/block/Kconfig gcc3.4.4/drivers/block/Kconfig
+--- linux/drivers/block/Kconfig 2005-11-09 13:53:31.000000000 +1100
++++ gcc3.4.4/drivers/block/Kconfig 2005-11-09 14:00:47.000000000 +1100
+@@ -190,6 +190,13 @@
+ To compile this driver as a module, choose M here: the
+ module will be called DAC960.
+
++config BLK_SSFDC
++ tristate "SmartMedia(TM) Driver (sm)"
++ depends on SH_TITAN
++ help
++ Say Y here if you want the SmartMedia chip enabled.
++ Otherwise say N.
++
+ config BLK_DEV_UMEM
+ tristate "Micro Memory MM5415 Battery Backed RAM support (EXPERIMENTAL)"
+ depends on PCI && EXPERIMENTAL
+diff -durN -X ../diff.ignore linux/drivers/block/Makefile gcc3.4.4/drivers/block/Makefile
+--- linux/drivers/block/Makefile 2004-12-25 08:35:24.000000000 +1100
++++ gcc3.4.4/drivers/block/Makefile 2005-11-09 14:00:47.000000000 +1100
+@@ -35,6 +35,7 @@
+ obj-$(CONFIG_BLK_CPQ_DA) += cpqarray.o
+ obj-$(CONFIG_BLK_CPQ_CISS_DA) += cciss.o
+ obj-$(CONFIG_BLK_DEV_DAC960) += DAC960.o
++obj-$(CONFIG_BLK_SSFDC) += ssfdc.o
+ obj-$(CONFIG_CDROM_PKTCDVD) += pktcdvd.o
+
+ obj-$(CONFIG_BLK_DEV_UMEM) += umem.o
+diff -durN -X ../diff.ignore linux/drivers/block/ssfdc.c gcc3.4.4/drivers/block/ssfdc.c
+--- linux/drivers/block/ssfdc.c 1970-01-01 10:00:00.000000000 +1000
++++ gcc3.4.4/drivers/block/ssfdc.c 2005-11-09 14:00:47.000000000 +1100
+@@ -0,0 +1,2738 @@
++/* $id: $
++ssfdc.c - Solid State Flopyy Disk Card
++
++Original source curtesy of Toshiba Corporation.
++
++Modification for use by Linux provided by Nimble Microsystems Inc.
++
++TODO:
++
++Modification History:
++
++ March 2001 - Initial port of Toshiba sources by Bill Mann
++ May 2001 - Debug of staticly linked ssfdc driver, Bill Mann
++ Nov 2001 - Reimplementation using tasklets and timers.
++ May 2002 - Partition support added.
++ Oct 2003 - Port to kernel 2.6.0
++ Mar 2004 - Stabilization refinements...
++
++Overview: The kernel interfaces to the device via the "block_device_operations
++ ssfdc_fops", the device's request handling function
++ "do_ssfdc_request(request_queue_t * q)", or by the ioctl interface ssfdc_ioctl().
++
++ do_ssfdc_request() purpose is to kickstart ssfdc_thread via a wake_up call. ssfdc_thread
++ then processes requests from the queue.
++
++ Blocks are mapped logically. So a sector read/write results in the determination
++ of the logical block address of the block containing the desired sector and the
++ corresponding physical block being accessed. Note the use of ReadBlock, WriteBlock,
++ and PhyBlock, Log2Phy[] etc.
++
++ This driver implements a wear leveling strategy where sector writes to the
++ SmartMedia causes the block which is the target of the write to be copied into a
++ new block, the new data written and the old block erased. This makes the driver
++ more complicated than a straightforward sector read/write.
++
++*/
++
++/* Section device headers */
++#define DEBUG_SSFDC 0
++#define DEBUG_SSFDC_STRUCT 0
++#define DEBUG_SSFDC_REQUEST 0
++#define DEBUG_SSFDC_READREDT 0
++#define DEBUG_SSFDC_WRITE 0
++#define DEBUG_SSFDC_WRITESECT 0
++#define DEBUG_SSFDC_WRITEBLKS 0
++#define DEBUG_SSFDC_READ 0
++#define DEBUG_SSFDC_ADDR 0
++#define DEBUG_SSFDC_ASSIGNRELEASE 0
++#define SSFDC_READINGTASKLET 0
++/* Edition Compilation Mode */
++
++#include <linux/module.h>
++
++#include <asm/delay.h>
++#include <linux/sched.h>
++#include <linux/interrupt.h>
++
++#include <linux/fs.h>
++#include <linux/hdreg.h>
++#include <linux/file.h>
++#include <linux/stat.h>
++#include <linux/time.h>
++#include <linux/errno.h>
++#include <linux/major.h>
++#include <linux/init.h>
++#include <linux/devfs_fs_kernel.h>
++#include <asm/uaccess.h>
++#include <asm/hardirq.h>
++#include <linux/bio.h>
++#include <linux/blkdev.h>
++#include <linux/slab.h>
++#include <linux/highmem.h>
++
++#include "ssfdc.h"
++
++#define SSFDC_MAJOR 240
++
++static int static_ssfdc_debug = 0;
++
++static DECLARE_WAIT_QUEUE_HEAD(ssfdc_wait);
++
++static struct gendisk *disks[MAX_SSFDC];
++static ssfdc_dev *ssfdc[MAX_SSFDC];
++
++static int ssfdc_open(struct inode *i_node, struct file *fptr);
++static int ssfdc_release(struct inode *i_node, struct file *fptr);
++static int ssfdc_ioctl(struct inode *i_node, struct file *fptr, unsigned cmd, unsigned long arg);
++static int ssfdc_revalidate(struct gendisk *disk);
++void do_ssfdc_request(request_queue_t * q);
++
++static struct block_device_operations ssfdc_fops = {
++ .owner = THIS_MODULE,
++ .open = ssfdc_open,
++ .release = ssfdc_release,
++ .ioctl = ssfdc_ioctl,
++ // bjm out .revalidate_disk = ssfdc_revalidate,
++};
++
++
++/***************************************************************************
++ BIT Control Macro
++ ***************************************************************************/
++static char BitData[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80 };
++#define SetBit(a,b) (a[(unsigned char)((b)/8)]|= BitData[(b)%8])
++#define ClrBit(a,b) (a[(unsigned char)((b)/8)]&=~BitData[(b)%8])
++#define ChkBit(a,b) (a[(unsigned char)((b)/8)] & BitData[(b)%8])
++
++/***************************************************************************/
++static int MediaReadSector(ssfdc_dev *, struct request *, char *, long,int);
++static int MediaWriteSector(ssfdc_dev *, struct request *, char *, long,int);
++
++/***************************************************************************/
++static int CheckLogCHS(ssfdc_dev *,unsigned int *,unsigned char *,unsigned char *);
++static int CheckMediaWP(ssfdc_dev *);
++static int ConvMediaAddr(ssfdc_dev *,long);
++static int IncMediaAddr(ssfdc_dev *);
++static int WriteReqInCurrBlk(ssfdc_dev *, long, int *);
++/******************************************/
++/******************************************/
++static int AssignWriteBlock(ssfdc_dev *, int);
++/******************************************/
++/******************************************/
++static int SetPhyFmtValue(ssfdc_dev *);
++static int SearchCIS(ssfdc_dev *,unsigned int *);
++static int MakeLogTable(ssfdc_dev *,unsigned int);
++/******************************************/
++static int MarkFailPhyOneBlock(ssfdc_dev *);
++
++static void _ReadSsfdcBuf(ssfdc_dev *, unsigned char *databuf,unsigned char *redundant);
++static void _WriteSsfdcBuf(ssfdc_dev *,unsigned char *,unsigned char *);
++static void _ReadSsfdcWord(ssfdc_dev *,unsigned int *);
++static void _ReadRedtSsfdcBuf(ssfdc_dev *, unsigned char *redundant);
++static void _WriteRedtSsfdcBuf(ssfdc_dev*, unsigned char *redundant);
++
++/***************************************************************************/
++static void _SetSsfdcCmd(ssfdc_dev *, unsigned char);
++static void _SetSsfdcAddr(ssfdc_dev *, unsigned char);
++static void _SetSsfdcBlock(ssfdc_dev *);
++static void _SetSsfdcChip(ssfdc_dev *);
++static void _SetSsfdcStandby(ssfdc_dev *);
++static int _CheckSsfdcBusy(ssfdc_dev *, unsigned int);
++static int _CheckSsfdcStatus(ssfdc_dev *);
++static void _ResetSsfdcErr(ssfdc_dev *psm);
++static unsigned char _CheckDevCode(unsigned char);
++void SsfdcReset(ssfdc_dev *);
++void CntReset(ssfdc_dev *);
++
++static char BitCount(unsigned char);
++static char BitCountWord(unsigned int);
++
++static void _WaitTimer(long int);
++typedef void (*timeout_fn)(unsigned long);
++static void ssfdc_rw_request(ssfdc_dev *psm, struct request *req);
++static int ssfdc_end_request(ssfdc_dev *psm, struct request *req, int status);
++static void ssfdc_terminate_request(ssfdc_dev *psm, struct request *req);
++static struct request *ssfdc_get_request(ssfdc_dev *psm);
++
++/* debugging utils etc. */
++
++#if DEBUG_SSFDC
++static void dump_ssfdc_state(ssfdc_dev * psm);
++#endif
++
++/* end of debugging utils etc. */
++
++/* our tasklets */
++/* top level R/W initiation tasklet */
++static void initxfer(unsigned long);
++#if 0 // use thread and not a tasklet
++DECLARE_TASKLET(initxfer_tasklet0, initxfer, 0);
++#ifdef CONFIG_SH_NIMBLE_MINI
++DECLARE_TASKLET(initxfer_tasklet1, initxfer, 1);
++#endif
++#endif
++
++/* Sector Write Tasklets, This group includes a readcopy tasklet for block copies...*/
++
++/* Tasklet to read a sector into a temporary buffer for later write */
++
++/* power is turned on, and then left on for TIMER_ON_TIMEOUT */
++// bjm debug struct timer_list mediachange_timer;
++// bjm debug static void mediachangetest(unsigned long);
++
++// bjm out
++// bjm out struct timer_list waiting_timer;
++static void waiting_timeout(unsigned long);
++
++/******************************************************************************/
++static void trans_result \
++ (unsigned char,unsigned char,unsigned char *,unsigned char *);
++static void calculate_ecc \
++ (unsigned char *,unsigned char *,unsigned char *,unsigned char *,unsigned char *);
++static unsigned char correct_data \
++ (unsigned char *,unsigned char *,unsigned char,unsigned char,unsigned char);
++
++ /* CP0-CP5 code table */
++static unsigned char ecctable[256] = {
++ 0x00,0x55,0x56,0x03,0x59,0x0C,0x0F,0x5A,0x5A,0x0F,0x0C,0x59,0x03,0x56,0x55,0x00,
++ 0x65,0x30,0x33,0x66,0x3C,0x69,0x6A,0x3F,0x3F,0x6A,0x69,0x3C,0x66,0x33,0x30,0x65,
++ 0x66,0x33,0x30,0x65,0x3F,0x6A,0x69,0x3C,0x3C,0x69,0x6A,0x3F,0x65,0x30,0x33,0x66,
++ 0x03,0x56,0x55,0x00,0x5A,0x0F,0x0C,0x59,0x59,0x0C,0x0F,0x5A,0x00,0x55,0x56,0x03,
++ 0x69,0x3C,0x3F,0x6A,0x30,0x65,0x66,0x33,0x33,0x66,0x65,0x30,0x6A,0x3F,0x3C,0x69,
++ 0x0C,0x59,0x5A,0x0F,0x55,0x00,0x03,0x56,0x56,0x03,0x00,0x55,0x0F,0x5A,0x59,0x0C,
++ 0x0F,0x5A,0x59,0x0C,0x56,0x03,0x00,0x55,0x55,0x00,0x03,0x56,0x0C,0x59,0x5A,0x0F,
++ 0x6A,0x3F,0x3C,0x69,0x33,0x66,0x65,0x30,0x30,0x65,0x66,0x33,0x69,0x3C,0x3F,0x6A,
++ 0x6A,0x3F,0x3C,0x69,0x33,0x66,0x65,0x30,0x30,0x65,0x66,0x33,0x69,0x3C,0x3F,0x6A,
++ 0x0F,0x5A,0x59,0x0C,0x56,0x03,0x00,0x55,0x55,0x00,0x03,0x56,0x0C,0x59,0x5A,0x0F,
++ 0x0C,0x59,0x5A,0x0F,0x55,0x00,0x03,0x56,0x56,0x03,0x00,0x55,0x0F,0x5A,0x59,0x0C,
++ 0x69,0x3C,0x3F,0x6A,0x30,0x65,0x66,0x33,0x33,0x66,0x65,0x30,0x6A,0x3F,0x3C,0x69,
++ 0x03,0x56,0x55,0x00,0x5A,0x0F,0x0C,0x59,0x59,0x0C,0x0F,0x5A,0x00,0x55,0x56,0x03,
++ 0x66,0x33,0x30,0x65,0x3F,0x6A,0x69,0x3C,0x3C,0x69,0x6A,0x3F,0x65,0x30,0x33,0x66,
++ 0x65,0x30,0x33,0x66,0x3C,0x69,0x6A,0x3F,0x3F,0x6A,0x69,0x3C,0x66,0x33,0x30,0x65,
++ 0x00,0x55,0x56,0x03,0x59,0x0C,0x0F,0x5A,0x5A,0x0F,0x0C,0x59,0x03,0x56,0x55,0x00
++};
++
++#define BIT7 0x80
++#define BIT6 0x40
++#define BIT5 0x20
++#define BIT4 0x10
++#define BIT3 0x08
++#define BIT2 0x04
++#define BIT1 0x02
++#define BIT0 0x01
++
++#define BIT1BIT0 0x03
++#define BIT23 0x00800000L
++#define MASK_CPS 0x3f
++#define CORRECTABLE 0x00555554L
++
++/*
++ Transfer result
++ LP14,12,10,... & LP15,13,11,... -> LP15,14,13,... & LP7,6,5,..
++*/
++static void trans_result(reg2,reg3,ecc1,ecc2)
++unsigned char reg2; /* LP14,LP12,LP10,... */
++unsigned char reg3; /* LP15,LP13,LP11,... */
++unsigned char *ecc1; /* LP15,LP14,LP13,... */
++unsigned char *ecc2; /* LP07,LP06,LP05,... */
++{
++ unsigned char a; /* Working for reg2,reg3 */
++ unsigned char b; /* Working for ecc1,ecc2 */
++ unsigned char i; /* For counting */
++
++ a=BIT7; b=BIT7; /* 80h=10000000b */
++ *ecc1=*ecc2=0; /* Clear ecc1,ecc2 */
++ for(i=0; i<4; ++i) {
++ if ((reg3&a)!=0) *ecc1|=b; /* LP15,13,11,9 -> ecc1 */
++ b=b>>1; /* Right shift */
++ if ((reg2&a)!=0) *ecc1|=b; /* LP14,12,10,8 -> ecc1 */
++ b=b>>1; /* Right shift */
++ a=a>>1; /* Right shift */
++ }
++ b=BIT7; /* 80h=10000000b */
++ for(i=0; i<4; ++i) {
++ if ((reg3&a)!=0) *ecc2|=b; /* LP7,5,3,1 -> ecc2 */
++ b=b>>1; /* Right shift */
++ if ((reg2&a)!=0) *ecc2|=b; /* LP6,4,2,0 -> ecc2 */
++ b=b>>1; /* Right shift */
++ a=a>>1; /* Right shift */
++ }
++}
++
++
++/*
++ Calculating ECC
++ data[0-255] -> ecc1,ecc2,ecc3 using CP0-CP5 code table[0-255]
++*/
++static void calculate_ecc(table,data,ecc1,ecc2,ecc3)
++unsigned char *table; /* CP0-CP5 code table */
++unsigned char *data; /* DATA */
++unsigned char *ecc1; /* LP15,LP14,LP13,... */
++unsigned char *ecc2; /* LP07,LP06,LP05,... */
++unsigned char *ecc3; /* CP5,CP4,CP3,...,"1","1" */
++{
++ unsigned int i; /* For counting */
++ unsigned char a; /* Working for table */
++ unsigned char reg1; /* D-all,CP5,CP4,CP3,... */
++ unsigned char reg2; /* LP14,LP12,L10,... */
++ unsigned char reg3; /* LP15,LP13,L11,... */
++
++ reg1=reg2=reg3=0; /* Clear parameter */
++
++ for(i=0; i<256; ++i) {
++ a=table[data[i]]; /* Get CP0-CP5 code from table */
++ reg1^=(a&MASK_CPS); /* XOR with a */
++ if ((a&BIT6)!=0) { /* If D_all(all bit XOR) = 1 */
++ reg3^=(unsigned char)i; /* XOR with counter */
++ reg2^=~((unsigned char)i); /* XOR with inv. of counter */
++ }
++ }
++
++ /* Trans LP14,12,10,... & LP15,13,11,... -> LP15,14,13,... & LP7,6,5,.. */
++ trans_result(reg2,reg3,ecc1,ecc2);
++
++ *ecc1=~(*ecc1); *ecc2=~(*ecc2); /* Inv. ecc2 & ecc3 */
++ *ecc3=((~reg1)<<2)|BIT1BIT0; /* Make TEL format */
++}
++
++static unsigned char correct_data(data,eccdata,ecc1,ecc2,ecc3)
++unsigned char *data; /* DATA */
++unsigned char *eccdata; /* ECC DATA */
++unsigned char ecc1; /* LP15,LP14,LP13,... */
++unsigned char ecc2; /* LP07,LP06,LP05,... */
++unsigned char ecc3; /* CP5,CP4,CP3,...,"1","1" */
++{
++ unsigned long l; /* Working to check d */
++ unsigned long d; /* Result of comparison */
++ unsigned int i; /* For counting */
++ unsigned char d1,d2,d3; /* Result of comparison */
++ unsigned char a; /* Working for add */
++ unsigned char add; /* Byte address of cor. DATA */
++ unsigned char b; /* Working for bit */
++ unsigned char bit; /* Bit address of cor. DATA */
++
++ d1=ecc1^eccdata[1]; d2=ecc2^eccdata[0]; /* Compare LP's */
++ d3=ecc3^eccdata[2]; /* Comapre CP's */
++ d=((unsigned long)d1<<16) /* Result of comparison */
++ +((unsigned long)d2<<8)
++ +(unsigned long)d3;
++
++ if (d==0) return(0); /* If No error, return */
++ if (((d^(d>>1))&CORRECTABLE)==CORRECTABLE) { /* If correctable */
++ l=BIT23;
++ add=0; /* Clear parameter */
++ a=BIT7;
++ for(i=0; i<8; ++i) { /* Checking 8 bit */
++ if ((d&l)!=0) add|=a; /* Make byte address from LP's */
++ l>>=2; a>>=1; /* Right Shift */
++ }
++ bit=0; /* Clear parameter */
++ b=BIT2;
++ for(i=0; i<3; ++i) { /* Checking 3 bit */
++ if ((d&l)!=0) bit|=b; /* Make bit address from CP's */
++ l>>=2; b>>=1; /* Right shift */
++ }
++ b=BIT0;
++ data[add]^=(b<<bit); /* Put corrected data */
++ return(1);
++ }
++ i=0; /* Clear count */
++ d&=0x00ffffffL; /* Masking */
++ while(d) { /* If d=0 finish counting */
++ if (d&BIT0) ++i; /* Count number of 1 bit */
++ d>>=1; /* Right shift */
++ }
++ if (i==1) { /* If ECC error */
++ eccdata[1]=ecc1; eccdata[0]=ecc2; /* Put right ECC code */
++ eccdata[2]=ecc3;
++ return(2);
++ }
++ return(3); /* Uncorrectable error */
++}
++/***************************************************************************
++ Common Subroutine
++ ***************************************************************************/
++char BitCount(unsigned char cdata)
++{
++ char bitcount=0;
++ while(cdata) {
++ bitcount+=(cdata &0x01);
++ cdata /=2;
++ }
++ return(bitcount);
++}
++
++char BitCountWord(unsigned int cdata)
++{
++ char bitcount=0;
++ while(cdata) {
++ bitcount+=(cdata &0x01);
++ cdata /=2;
++ }
++ return(bitcount);
++}
++
++/***************************************************************************/
++void StringCopy(char *stringA, char *stringB, int count)
++{
++ int i;
++ for(i=0; i<count; i++)
++ *stringA++ = *stringB++;
++}
++
++int StringCmp(char *stringA, char *stringB, int count)
++{
++ int i;
++ for (i=0;i<count;i++)
++ if (*stringA++ != *stringB++) return(ERROR);
++ return(SUCCESS);
++}
++/***************************************************************************/
++int CheckDataBlank(unsigned char *redundant)
++{
++ char i;
++ for(i=0; i<REDTSIZE; i++)
++ if(*redundant++!=0xFF) return(ERROR);
++ return(SUCCESS);
++}
++
++int CheckFailBlock(unsigned char *redundant)
++{
++ redundant+=REDT_BLOCK;
++ if(*redundant==0xFF) return(SUCCESS);
++ if(! *redundant) return(ERROR);
++ if(BitCount(*redundant)<7) return(ERROR);
++ return(SUCCESS);
++}
++
++int CheckCisBlock(unsigned char *redundant)
++{
++ if(! (*(redundant+REDT_ADDR1H)|*(redundant+REDT_ADDR1L)))
++ return(SUCCESS);
++ if(! (*(redundant+REDT_ADDR2H)|*(redundant+REDT_ADDR2L)))
++ return(SUCCESS);
++ return(ERROR);
++}
++
++int CheckDataStatus(unsigned char *redundant)
++{
++ redundant+=REDT_DATA;
++ if(*redundant==0xFF) return(SUCCESS);
++ if(! *redundant) return(ERROR);
++ if(BitCount(*redundant)<5) return(ERROR);
++ return(SUCCESS);
++}
++
++int LoadLogBlockAddr(ssfdc_dev *psm)
++{
++ unsigned int addr1,addr2;
++ addr1=*(psm->Redundant+REDT_ADDR1H)*0x100+*(psm->Redundant+REDT_ADDR1L);
++ addr2=*(psm->Redundant+REDT_ADDR2H)*0x100+*(psm->Redundant+REDT_ADDR2L);
++ if(addr1==addr2)
++ if((addr1 &0xF000)==0x1000)
++ { psm->LogBlock=(addr1 &0x0FFF)/2; return(SUCCESS); }
++ if(BitCountWord(addr1^addr2)>1) return(ERROR);
++ if((addr1 &0xF000)==0x1000)
++ if(! (BitCountWord(addr1) &0x0001))
++ { psm->LogBlock=(addr1 &0x0FFF)/2; return(SUCCESS); }
++ if((addr2 &0xF000)==0x1000)
++ if(! (BitCountWord(addr2) &0x0001))
++ { psm->LogBlock=(addr2 &0x0FFF)/2; return(SUCCESS); }
++ return(ERROR);
++}
++/***************************************************************************/
++void ClrRedundantData(unsigned char *redundant)
++{
++ char i;
++ for(i=0; i<REDTSIZE; i++) *(redundant+i)=0xFF;
++}
++
++/***************************************************************************/
++void SetLogBlockAddr(ssfdc_dev *psm, unsigned char *redundant)
++{
++ unsigned int addr;
++ *(redundant+REDT_BLOCK)=0xFF;
++ *(redundant+REDT_DATA) =0xFF;
++ addr=psm->LogBlock*2+0x1000;
++ if((BitCountWord(addr)%2)) addr++;
++ *(redundant+REDT_ADDR1H)=*(redundant+REDT_ADDR2H)=addr/0x100;
++ *(redundant+REDT_ADDR1L)=*(redundant+REDT_ADDR2L)=(unsigned char)addr;
++}
++
++void SetFailBlock(unsigned char *redundant)
++{
++ char i;
++ for(i=0; i<REDTSIZE; i++)
++ *redundant++=((i==REDT_BLOCK)?0xF0:0xFF);
++}
++
++void SetDataStatus(unsigned char *redundant)
++{
++ redundant+=REDT_DATA;
++ *redundant=0x00;
++}
++
++
++/***************************************************************************
++ NAND Memory (SmartMedia) Control Subroutine
++ ***************************************************************************/
++static void _SetSsfdcCmd(ssfdc_dev *psm, unsigned char cmd)
++{
++ _HwSetCmd(psm);
++ _HwOutData(psm,cmd);
++ _HwSetData(psm);
++}
++
++static void _SetSsfdcAddr(ssfdc_dev *psm, unsigned char add)
++{
++ unsigned int addr;
++
++#if DEBUG_SSFDC_ADDR
++ printk(KERN_DEBUG "_SetSsfdcAddr() Zone %d LogBlock %d PhyBlock %d Sector %d\n",
++ psm->Zone,psm->LogBlock,psm->PhyBlock,psm->Sector);
++#endif
++ addr=(unsigned int)psm->Zone*psm->MaxBlocks+psm->PhyBlock;
++ addr=addr*(unsigned int)psm->MaxSectors+psm->Sector;
++ if((psm->Attribute &MPS)==PS256) /* for 256byte/page */
++ addr=addr*2+(unsigned int)add;
++/*-----------------------------------------------*/
++ _HwSetAddr(psm);
++ _HwOutData(psm,0x00);
++ _HwOutData(psm,(unsigned char)addr);
++ _HwOutData(psm,(unsigned char)(addr/0x0100));
++ if((psm->Attribute &MADC)==AD4CYC)
++ _HwOutData(psm,(unsigned char)(psm->Zone/2)); /* Patch */
++ _HwSetData(psm);
++}
++
++static void _SetSsfdcBlock(ssfdc_dev *psm)
++{
++ unsigned int addr;
++#if DEBUG_SSFDC_ASSIGNRELEASE
++ printk(KERN_DEBUG "_SetSsfdcBlock() set card addr to PhyBlock %d\n", psm->PhyBlock);
++#endif
++ addr=(unsigned int)psm->Zone*psm->MaxBlocks+psm->PhyBlock;
++ addr=addr*(unsigned int)psm->MaxSectors;
++ if((psm->Attribute &MPS)==PS256) /* for 256byte/page */
++ addr=addr*2;
++/*-----------------------------------------------*/
++ _HwSetAddr(psm);
++ _HwOutData(psm,(unsigned char)addr);
++ _HwOutData(psm,(unsigned char)(addr/0x0100));
++ if((psm->Attribute &MADC)==AD4CYC)
++ _HwOutData(psm,(unsigned char)(psm->Zone/2)); /* Patch */
++ _HwSetData(psm);
++}
++
++static inline void _SetSsfdcStandby(ssfdc_dev *psm)
++{
++ _HwSetStandby(psm);
++}
++
++static int _CheckSsfdcStatus(ssfdc_dev *psm)
++{
++ int status;
++ if((status=_HwInData(psm)) & WR_FAIL) {
++ printk(KERN_DEBUG "_CheckSsfdcStatus() error %x\n", status);
++ return(ERROR);
++ }
++ return(SUCCESS);
++}
++
++static void _ResetSsfdcErr(ssfdc_dev *psm)
++{
++ _HwSetCmd(psm);
++ _HwOutData(psm,SSFDC_RST_CHIP);
++ _HwSetData(psm);
++ while(1) {
++ udelay(30);
++ if(! _HwChkBusy(psm)) break;
++ }
++ _HwSetStandby(psm);
++}
++
++static void waiting_timeout(unsigned long psm)
++{
++ // enable the wakeup signal!
++ wake_up(&((ssfdc_dev *)psm)->thread_wq);
++}
++
++/*
++ _CheckSsfdcBusy()
++
++ set a timer in jiffies from int time x .1ms
++*/
++
++static int _CheckSsfdcBusy(ssfdc_dev *psm, unsigned int time)
++{
++ unsigned long incr_div = 4;
++ unsigned long incr_us = time / incr_div,
++ jticks=time/(MSEC * JIFFY_TICK_MS);
++ unsigned long tick_retried=0, wrap_flag, expires;
++
++ if (!jticks) {
++ // small delay first to test completion
++ do {
++ udelay(incr_us);
++ if (!_HwChkBusy(psm))
++ return(SUCCESS);
++ } while (incr_div--);
++ return(ERROR);
++ }
++
++ // Block the wakeup signal?
++
++one_more_time:
++ expires = jiffies + jticks;
++ wrap_flag = ( expires < jiffies);
++
++ do {
++ wait_event_interruptible_timeout(psm->thread_wq, 0, jticks);
++ if (!_HwChkBusy(psm)) {
++ return(SUCCESS);
++ }
++ } while (wrap_flag ? expires <= jiffies : expires >= jiffies);
++
++#if 1
++ // Is the chip not busy? If so its an ERROR
++ if (!_HwChkBusy(psm)) {
++ return(SUCCESS);
++ }
++ else {
++ // if we came back, give us one more tick/time
++ if (! tick_retried ) {
++ tick_retried = 1;
++ jticks = 0;
++ printk(".");
++ goto one_more_time;
++ }
++ return(ERROR);
++ }
++#endif
++}
++
++static void _SetSsfdcChip(ssfdc_dev *psm)
++{
++ _HwSetAddr(psm);
++ _HwOutData(psm,0x00);
++ _HwSetData(psm);
++}
++/***************************************************************************
++ NAND Memory (SmartMedia) Buffer Data Xfer Subroutine
++ ***************************************************************************/
++static void _ReadSsfdcBuf(ssfdc_dev *psm,unsigned char *databuf,unsigned char *redundant)
++{
++ int i;
++ for(i=0x00;i<(((psm->Attribute &MPS)==PS256)?0x100:0x200);i++)
++ *databuf++ =_HwInData(psm);
++ for(i=0x00;i<(((psm->Attribute &MPS)==PS256)?0x08:0x10);i++)
++ *redundant++ =_HwInData(psm);
++}
++
++static void _WriteSsfdcBuf(ssfdc_dev *psm, unsigned char *databuf,unsigned char *redundant)
++{
++ int i;
++ for(i=0x00;i<(((psm->Attribute &MPS)==PS256)?0x100:0x200);i++)
++ _HwOutData(psm,*databuf++);
++ for(i=0x00;i<(((psm->Attribute &MPS)==PS256)?0x08:0x10);i++)
++ _HwOutData(psm,*redundant++);
++}
++
++static void _ReadSsfdcWord(ssfdc_dev *psm, unsigned int *pdata)
++{
++ *pdata =_HwInData(psm)*0x100;
++ *pdata|=(unsigned char)_HwInData(psm);
++}
++
++static void _ReadRedtSsfdcBuf(ssfdc_dev *psm,unsigned char *redundant)
++{
++ int i;
++ for(i=0x00;i<(((psm->Attribute &MPS)==PS256)?0x08:0x10);i++)
++ redundant[i] =_HwInData(psm);
++}
++
++static void _WriteRedtSsfdcBuf(ssfdc_dev *psm, unsigned char *redundant)
++{
++ char i;
++ for(i=0x00;i<(((psm->Attribute &MPS)==PS256)?0x08:0x10);i++)
++ _HwOutData(psm,*redundant++);
++}
++
++/***************************************************************************
++ Timer Control Subroutine
++ ***************************************************************************/
++#define SHORT_DELAY 1
++
++
++
++
++void _GetDateTime(char *date)
++{
++}
++
++/*
++_WaitTimer(long time) time is in ticks.
++*/
++
++static inline void _WaitTimer(long time)
++{
++}
++
++/***************************************************************************
++ SmartMedia Function Command Subroutine
++ ***************************************************************************/
++void SsfdcReset(ssfdc_dev *psm)
++{
++ _SetSsfdcCmd(psm, SSFDC_RST_CHIP);
++ _CheckSsfdcBusy(psm,BUSY_RESET);
++ _SetSsfdcCmd(psm,SSFDC_READ);
++ _CheckSsfdcBusy(psm,BUSY_READ);
++ _SetSsfdcStandby(psm);
++}
++
++void SsfdcWriteRedtMode(ssfdc_dev *psm)
++{
++ _SetSsfdcCmd(psm,SSFDC_RST_CHIP);
++ _CheckSsfdcBusy(psm,BUSY_RESET);
++ _SetSsfdcCmd(psm,SSFDC_READ_REDT);
++ _CheckSsfdcBusy(psm,BUSY_READ);
++ _SetSsfdcStandby(psm);
++}
++
++void SsfdcReadID(ssfdc_dev *psm, unsigned int *pid)
++{
++ _SetSsfdcCmd(psm,SSFDC_READ_ID);
++ _SetSsfdcChip(psm);
++ _ReadSsfdcWord(psm,pid);
++ _SetSsfdcStandby(psm);
++}
++
++int SsfdcCheckStatus(ssfdc_dev *psm)
++{
++ _SetSsfdcCmd(psm,SSFDC_RDSTATUS);
++ if(_CheckSsfdcStatus(psm))
++ { _SetSsfdcStandby(psm); return(ERROR); }
++ _SetSsfdcStandby(psm);
++ return(SUCCESS);
++}
++
++int SsfdcReadSect(ssfdc_dev *psm, unsigned char *buf,unsigned char *redundant)
++{
++#if DEBUG_SSFDC_READ
++ printk(KERN_DEBUG "SsfdcReadSect() - Zone %d LogBlock %d, PhyBlock %d, Sector %d\n",
++ psm->Zone, psm->LogBlock, psm->PhyBlock, psm->Sector);
++#endif
++ _SetSsfdcCmd(psm,SSFDC_READ);
++ _SetSsfdcAddr(psm, EVEN);
++ if(_CheckSsfdcBusy(psm,BUSY_READ))
++ { _ResetSsfdcErr(psm); return(ERROR); }
++ _ReadSsfdcBuf(psm,buf,redundant);
++ if(_CheckSsfdcBusy(psm,BUSY_READ))
++ { _ResetSsfdcErr(psm); return(ERROR); }
++ if((psm->Attribute &MPS)==PS256) {
++ _SetSsfdcCmd(psm,SSFDC_READ);
++ _SetSsfdcAddr(psm, ODD);
++ if(_CheckSsfdcBusy(psm,BUSY_READ))
++ { _ResetSsfdcErr(psm); return(ERROR); }
++ _ReadSsfdcBuf(psm,buf+0x100,redundant+0x08);
++ if(_CheckSsfdcBusy(psm,BUSY_READ))
++ { _ResetSsfdcErr(psm); return(ERROR); }
++ }
++ _SetSsfdcStandby(psm);
++ return(SUCCESS);
++}
++
++int SsfdcWriteSect(ssfdc_dev *psm, unsigned char *buf, unsigned char *redundant)
++{
++#if DEBUG_SSFDC_WRITESECT
++ printk(KERN_DEBUG "SsfdcWriteSect() - Zone %d LogBlock %d, PhyBlock %d, Sector %d\n", \
++ psm->Zone, psm->LogBlock, psm->PhyBlock, psm->Sector);
++#endif
++ _SetSsfdcCmd(psm,SSFDC_WRDATA);
++ _SetSsfdcAddr(psm,EVEN);
++ _WriteSsfdcBuf(psm,buf,redundant);
++ _SetSsfdcCmd(psm,SSFDC_WRITE);
++ if(_CheckSsfdcBusy(psm,BUSY_PROG))
++ { _ResetSsfdcErr(psm);
++#if DEBUG_SSFDC_WRITESECT
++ printk(KERN_DEBUG "SsfdcWriteSect() e 1\n");
++#endif
++ return(ERROR); }
++ if((psm->Attribute &MPS)==PS256) {
++ _SetSsfdcCmd(psm,SSFDC_RDSTATUS);
++ if(_CheckSsfdcStatus(psm))
++ { _SetSsfdcStandby(psm); return(SUCCESS); }
++ _SetSsfdcCmd(psm,SSFDC_WRDATA);
++ _SetSsfdcAddr(psm,ODD);
++ _WriteSsfdcBuf(psm,buf+0x100,redundant+0x08);
++ _SetSsfdcCmd(psm,SSFDC_WRITE);
++ if(_CheckSsfdcBusy(psm,BUSY_PROG))
++ { _ResetSsfdcErr(psm);
++#if DEBUG_SSFDC_WRITESECT
++ printk(KERN_DEBUG "SsfdcWriteSect() e 2\n");
++#endif
++ return(ERROR); }
++ }
++ _SetSsfdcStandby(psm);
++ return(SUCCESS);
++}
++
++int SsfdcEraseBlock(ssfdc_dev *psm)
++{
++ _SetSsfdcCmd(psm,SSFDC_ERASE1);
++ _SetSsfdcBlock(psm);
++ _SetSsfdcCmd(psm,SSFDC_ERASE2);
++ if(_CheckSsfdcBusy(psm,BUSY_ERASE) || SsfdcCheckStatus(psm)) {
++ _ResetSsfdcErr(psm);
++ return(ERROR);
++ }
++ _SetSsfdcStandby(psm);
++ return(SUCCESS);
++}
++
++int SsfdcReadRedtData(ssfdc_dev *psm, unsigned char *redundant)
++{
++#if DEBUG_SSFDC_READREDT
++ printk(KERN_DEBUG " +");
++#endif
++ _SetSsfdcCmd(psm,SSFDC_READ_REDT);
++ _SetSsfdcAddr(psm,EVEN);
++ if(_CheckSsfdcBusy(psm,BUSY_READ))
++ { _ResetSsfdcErr(psm);
++#if DEBUG_SSFDC_READREDT
++ printk(KERN_DEBUG " e 1\n");
++#endif
++ return(ERROR); }
++ _ReadRedtSsfdcBuf(psm, redundant);
++ if(_CheckSsfdcBusy(psm,BUSY_READ))
++ { _ResetSsfdcErr(psm);
++#if DEBUG_SSFDC_READREDT
++ printk(KERN_DEBUG " e 2\n");
++#endif
++ return(ERROR); }
++ if((psm->Attribute &MPS)==PS256) {
++ _SetSsfdcCmd(psm,SSFDC_READ_REDT);
++ _SetSsfdcAddr(psm,ODD);
++ if(_CheckSsfdcBusy(psm,BUSY_READ))
++ { _ResetSsfdcErr(psm);
++#if DEBUG_SSFDC_READREDT
++ printk(KERN_DEBUG " e 3\n");
++#endif
++
++ return(ERROR); }
++ _ReadRedtSsfdcBuf(psm, redundant+0x08);
++ if(_CheckSsfdcBusy(psm,BUSY_READ))
++ { _ResetSsfdcErr(psm);
++#if DEBUG_SSFDC_READREDT
++ printk(KERN_DEBUG " e 4\n");
++#endif
++ return(ERROR); }
++ }
++ _SetSsfdcStandby(psm);
++#if DEBUG_SSFDC_READREDT
++ printk(KERN_DEBUG " -\n");
++#endif
++ return(SUCCESS);
++}
++
++int SsfdcWriteRedtData(ssfdc_dev *psm, unsigned char *redundant)
++{
++ _SetSsfdcCmd(psm,SSFDC_WRDATA);
++ _SetSsfdcAddr(psm,EVEN);
++ _WriteRedtSsfdcBuf(psm,redundant);
++ _SetSsfdcCmd(psm,SSFDC_WRITE);
++ if(_CheckSsfdcBusy(psm,BUSY_PROG))
++ { _ResetSsfdcErr(psm); return(ERROR); }
++ if((psm->Attribute &MPS)==PS256) {
++ _SetSsfdcCmd(psm,SSFDC_RDSTATUS);
++ if(_CheckSsfdcStatus(psm))
++ { _SetSsfdcStandby(psm); return(SUCCESS); }
++ _SetSsfdcCmd(psm,SSFDC_WRDATA);
++ _SetSsfdcAddr(psm,ODD);
++ _WriteRedtSsfdcBuf(psm,redundant+0x08);
++ _SetSsfdcCmd(psm,SSFDC_WRITE);
++ if(_CheckSsfdcBusy(psm,BUSY_PROG))
++ { _ResetSsfdcErr(psm); return(ERROR); }
++ }
++ _SetSsfdcStandby(psm);
++ return(SUCCESS);
++}
++
++/***************************************************************************
++ SmartMedia ID Code Check & Mode Set Subroutine
++ ***************************************************************************/
++int SetSsfdcModel(ssfdc_dev *psm, unsigned char dcode)
++{
++ switch(_CheckDevCode(dcode)) {
++ case SSFDC1MB:
++ psm->Model = SSFDC1MB;
++ psm->Attribute = FLASH | AD3CYC | BS16 | PS256;
++ psm->MaxZones = 1;
++ psm->MaxBlocks = 256;
++ psm->MaxLogBlocks = 250;
++ psm->MaxSectors = 8;
++ break;
++ case SSFDC2MB:
++ psm->Model = SSFDC2MB;
++ psm->Attribute = FLASH | AD3CYC | BS16 | PS256;
++ psm->MaxZones = 1;
++ psm->MaxBlocks = 512;
++ psm->MaxLogBlocks = 500;
++ psm->MaxSectors = 8;
++ break;
++ case SSFDC4MB:
++ psm->Model = SSFDC4MB;
++ psm->Attribute = FLASH | AD3CYC | BS16 | PS512;
++ psm->MaxZones = 1;
++ psm->MaxBlocks = 512;
++ psm->MaxLogBlocks = 500;
++ psm->MaxSectors = 16;
++ break;
++ case SSFDC8MB:
++ psm->Model = SSFDC8MB;
++ psm->Attribute = FLASH | AD3CYC | BS16 | PS512;
++ psm->MaxZones = 1;
++ psm->MaxBlocks = 1024;
++ psm->MaxLogBlocks = 1000;
++ psm->MaxSectors = 16;
++ break;
++ case SSFDC16MB:
++ psm->Model = SSFDC16MB;
++ psm->Attribute = FLASH | AD3CYC | BS32 | PS512;
++ psm->MaxZones = 1;
++ psm->MaxBlocks = 1024;
++ psm->MaxLogBlocks = 1000;
++ psm->MaxSectors = 32;
++ break;
++ case SSFDC32MB:
++ psm->Model = SSFDC32MB;
++ psm->Attribute = FLASH | AD3CYC | BS32 | PS512;
++ psm->MaxZones = 2;
++ psm->MaxBlocks = 1024;
++ psm->MaxLogBlocks = 1000;
++ psm->MaxSectors = 32;
++ break;
++ case SSFDC64MB:
++ psm->Model = SSFDC64MB;
++ psm->Attribute = FLASH | AD4CYC | BS32 | PS512;
++ psm->MaxZones = 4;
++ psm->MaxBlocks = 1024;
++ psm->MaxLogBlocks = 1000;
++ psm->MaxSectors = 32;
++ break;
++ case SSFDC128MB:
++ psm->Model = SSFDC128MB;
++ psm->Attribute = FLASH | AD4CYC | BS32 | PS512;
++ psm->MaxZones = 8;
++ psm->MaxBlocks = 1024;
++ psm->MaxLogBlocks = 1000;
++ psm->MaxSectors = 32;
++ break;
++ default:
++ psm->Model = NOSSFDC;
++ return(ERROR);
++ }
++ return(SUCCESS);
++}
++
++/***************************************************************************/
++static unsigned char _CheckDevCode(unsigned char dcode)
++{
++ switch(dcode){
++ case 0x6E:
++ case 0xE8:
++ case 0xEC: return(SSFDC1MB); /* 8Mbit (1M) NAND */
++ case 0x64:
++ case 0xEA: return(SSFDC2MB); /* 16Mbit (2M) NAND */
++ case 0x6B:
++ case 0xE3:
++ case 0xE5: return(SSFDC4MB); /* 32Mbit (4M) NAND */
++ case 0xE6: return(SSFDC8MB); /* 64Mbit (8M) NAND */
++ case 0x73: return(SSFDC16MB); /*128Mbit (16M)NAND */
++ case 0x75: return(SSFDC32MB); /*256Mbit (32M)NAND */
++ case 0x76: return(SSFDC64MB); /*512Mbit (64M)NAND */
++ case 0x79: return(SSFDC128MB); /* 1Gbit(128M)NAND */
++ default: return(ERROR);
++ }
++}
++/***************************************************************************
++ SmartMedia Power Control Subroutine
++ ***************************************************************************/
++void CntReset(ssfdc_dev *psm)
++{
++ _HwSetStandby(psm);
++ _HwVccOff(psm);
++}
++
++int CntPowerOn(ssfdc_dev *psm)
++{
++ _HwVccOn(psm);
++ _WaitTimer(TIME_PON);
++ if(_HwChkPower(psm))
++ return(SUCCESS);
++ _HwVccOff(psm);
++ return(ERROR);
++}
++
++#if 0 // remove for now
++static void mediachangetest(unsigned long dev_idx)
++{
++ ssfdc_dev *psm = ssfdc[dev_idx];
++ unsigned int cardpresent;
++ unsigned long flags;
++
++ spin_lock_irqsave( &psm->req_queue_lock, flags );
++ // bjm spin_lock( &psm->req_queue_lock);
++
++ del_timer(&mediachange_timer);
++
++ // check current card presence
++ if ( ! (cardpresent = CntPowerOn(psm)) && psm->CardPresent ) {
++ psm->MediaChange = 1;
++ psm->DataBuf_Valid = 0;
++ }
++ psm->CardPresent = cardpresent;
++
++ // set up to run again...
++ mediachange_timer.function = mediachangetest;
++ mediachange_timer.expires = jiffies + (HZ / 2);
++ mediachange_timer.data = dev_idx;
++ add_timer(&mediachange_timer);
++
++ spin_unlock_irqrestore( &psm->req_queue_lock, flags );
++ // bjm spin_unlock( &psm->req_queue_lock);
++}
++#endif
++
++int CheckCardExist(ssfdc_dev *psm)
++{
++ char i,j,k;
++ if(! _HwChkStatus(psm)) /***** Not Status Change *****/
++ if(_HwChkCardIn(psm)) return(SUCCESS); /* Card exist in Slot */
++ for(i=0,j=0,k=0; i<0x10; i++) {
++ if(_HwChkCardIn(psm)) /***** Status Change *****/
++ { j++; k=0; }
++ else { j=0; k++; }
++ if(j>3) return(SUCCESS); /* Card exist in Slot */
++ if(k>3) return(ERROR); /* NO Card exist in Slot */
++ _WaitTimer(TIME_CDCHK);
++ }
++ return(ERROR);
++}
++
++int CheckSsfdcWP(ssfdc_dev *psm)
++{ /* ERROR: WP, SUCCESS: Not WP */
++ char i;
++ for(i=0; i<0x08; i++) {
++ if(_HwChkWP(psm))
++ return(ERROR);
++ _WaitTimer(TIME_WPCHK);
++ }
++ return(SUCCESS);
++}
++
++/******************************************/
++int CheckCISdata(unsigned char *buf,unsigned char *redundant)
++{
++ static unsigned char cis[]={ 0x01,0x03,0xD9,0x01,0xFF,0x18,0x02,0xDF,0x01,0x20 };
++ unsigned char ecc1,ecc2,ecc3;
++ unsigned int err;
++ calculate_ecc(ecctable,buf,&ecc1,&ecc2,&ecc3);
++ err=correct_data(buf,redundant+0x0D,ecc1,ecc2,ecc3);
++ if(err==0 || err==1 || err==2)
++ return(StringCmp(buf,cis,10));
++ buf+=0x100;
++ calculate_ecc(ecctable,buf,&ecc1,&ecc2,&ecc3);
++ err=correct_data(buf,redundant+0x08,ecc1,ecc2,ecc3);
++ if(err==0 || err==1 || err==2)
++ return(StringCmp(buf,cis,10));
++ return(ERROR);
++}
++
++int CheckECCdata(unsigned char *buf,unsigned char *redundant)
++{
++ unsigned char ecc1,ecc2,ecc3;
++ unsigned int err, corr=SUCCESS;
++ calculate_ecc(ecctable,buf,&ecc1,&ecc2,&ecc3);
++ err=correct_data(buf,redundant+0x0D,ecc1,ecc2,ecc3);
++ if(err==1 || err==2) corr=CORRECT;
++ else if(err) return(ERROR);
++ buf+=0x100;
++ calculate_ecc(ecctable,buf,&ecc1,&ecc2,&ecc3);
++ err=correct_data(buf,redundant+0x08,ecc1,ecc2,ecc3);
++ if(err==1 || err==2) corr=CORRECT;
++ else if(err) return(ERROR);
++ return(corr);
++}
++
++void SetECCdata(unsigned char *buf,unsigned char *redundant)
++{
++ calculate_ecc(ecctable,buf,redundant+0x0E,redundant+0x0D,redundant+0x0F);
++ buf+=0x100;
++ calculate_ecc(ecctable,buf,redundant+0x09,redundant+0x08,redundant+0x0A);
++}
++
++/***************************************************************************
++ Power Control & Media Exist Check Function
++ ***************************************************************************/
++
++/***************************************************************************
++ SmartMedia Read/Write/Erase Function
++ ***************************************************************************/
++static int MediaReadSector(ssfdc_dev *psm, struct request *req,
++ char * bbuf, long start,int count)
++{
++ char *buf;
++ int i, err, request_complete,
++ PrevBlock = NO_ASSIGN;
++ int read_status=0;
++
++ if (ConvMediaAddr(psm, start)) {
++ printk(KERN_ERR "MediaReadSector() - bad address conversion\n");
++ goto read_exit;
++ }
++
++ psm->ReqSectorSize = count;
++ psm->BufIndex = 0;
++ psm->RetryCount = 0;
++
++#if DEBUG_SSFDC_READ
++ printk(KERN_DEBUG "MediaReadSector() - read %d sectors @ %d\n", psm->ReqSectorSize, start);
++#endif
++ while (psm->ReqSectorSize) {
++ // if this PhyBlock is not assigned, fill with dummy data and return
++ // An assigned block results in a card access and readsector schedule...
++ if (psm->PhyBlock == NO_ASSIGN) {
++#if DEBUG_SSFDC_READ
++ printk(KERN_DEBUG "Read NO_ASSIGN block %x\n", psm->PhyBlock);
++#endif
++ buf = bbuf + psm->BufIndex;
++ for(i=0; i<SSFDC_SECTSIZE; i++)
++ *buf++=DUMMY_DATA;
++ }
++ else {
++ // send our command
++ if (PrevBlock != psm->PhyBlock) {
++#if DEBUG_SSFDC_READ
++ printk(KERN_DEBUG "Read block %x\n", psm->PhyBlock);
++#endif
++ PrevBlock = psm->PhyBlock;
++ _SetSsfdcCmd(psm,SSFDC_READ);
++ _SetSsfdcAddr(psm, EVEN);
++ for (i=0; i<5; ++i) {
++ if (!_HwChkBusy(psm))
++ break;
++ udelay(10);
++ }
++ }
++
++
++ if ( _HwChkBusy(psm) ) {
++ ++psm->Sect_rd_errs_ttl;
++#if DEBUG_SSFDC_READ
++ printk(KERN_DEBUG "MediaReadSector() - Hardware busy!\n");
++#endif
++ }
++ else {
++ ++psm->Sector_reads;
++ _ReadSsfdcBuf( psm, psm->SectBuf, psm->Redundant);
++
++ // verify the integrity of what was read
++ if (CheckDataStatus(psm->Redundant)) {
++#if DEBUG_SSFDC_READ
++ printk(KERN_DEBUG "Bad Data Status\n");
++#endif
++ goto error_state;
++ }
++
++ switch (err = CheckECCdata(psm->SectBuf,psm->Redundant))
++ {
++ case CORRECT:
++ // Correctable data, fix and copy like SUCCESS
++ SetECCdata(psm->SectBuf,psm->Redundant);
++ case SUCCESS:
++ memcpy(bbuf + psm->BufIndex, psm->SectBuf, SSFDC_SECTSIZE);
++ break;
++
++ case ERROR:
++error_state:
++ ++psm->Sect_rd_errs_ttl;
++#if DEBUG_SSFDC_READ
++ printk(KERN_DEBUG "readsector() - err == ERROR\n");
++#endif
++ _ResetSsfdcErr(psm);
++ if (++psm->RetryCount < RD_RETRY_LIMIT) {
++ continue;
++ }
++ break;
++ default:
++ ssfdc_terminate_request( psm, req);
++ break;
++ }
++
++ } // if ( _HwChkBusy(psm) )
++ } // if (psm->PhyBlock == NO_ASSIGN)
++
++ // common req/buffer management code for either unassigned or assigned
++ // block from /dev/ssfdc
++ psm->RetryCount = 0;
++ psm->BufIndex += SSFDC_SECTSIZE;
++ request_complete = (--psm->ReqSectorSize == 0);
++ if (request_complete) {
++ // completed the read, req->buffer now has requested sector(s).
++ // End the request waking sleeping process and reschedule initxfer().
++#if DEBUG_SSFDC_READ
++ printk(KERN_DEBUG "readsector() - req %x complete\n", req);
++#endif
++ read_status = 1;
++ }
++ else if (IncMediaAddr(psm)) {
++ printk(KERN_DEBUG "readsector() - IncMediaAddr() error.\n");
++ goto read_exit;
++ }
++ } // while (psm->ReqSectorSize)
++
++read_exit:
++ psm->XferState = xfer_idle;
++
++ return read_status;
++
++}
++
++/*
++ ReadBlkCopy(ssfdc_dev *psm, unsigned char *buf)
++*/
++int ReadBlkCopy(ssfdc_dev *psm, unsigned char *buf, char *rd_sector_status)
++{
++ int err, read_error=0, rw_retry=0;
++ unsigned long PrevBlock=NO_ASSIGN;
++
++ if ( ! buf ) {
++ printk(KERN_ERR "NULL buffer pointer\n");
++ return ERROR;
++ }
++
++ if (psm->PhyBlock == NO_ASSIGN) {
++ memset(buf, 0xff, psm->MaxSectors * SSFDC_SECTSIZE);
++ memset(rd_sector_status, 1, sizeof(char) * MAX_SECTNUM);
++ return SUCCESS;
++ }
++
++#if 0
++ printk(KERN_ERR "ReadBlkCopy() - LogBlk %d\n", psm->LogBlock);
++#endif
++
++ for (psm->Sector = 0;
++ psm->PhyBlock != NO_ASSIGN && psm->Sector < psm->MaxSectors;
++ ++psm->Sector)
++ {
++ if (PrevBlock != psm->PhyBlock) {
++ _SetSsfdcCmd(psm,SSFDC_READ);
++ _SetSsfdcAddr(psm, EVEN);
++ PrevBlock = psm->PhyBlock;
++ _CheckSsfdcBusy(psm, BUSY_ADDR_SET);
++ }
++
++ if ( _HwChkBusy(psm) ) {
++ printk(KERN_ERR "%s: HW busy during block copy!\n", MAJOR_NAME);
++ goto error_state;
++ }
++
++ _ReadSsfdcBuf( psm, psm->SectBuf, psm->Redundant);
++ if (CheckDataStatus(psm->Redundant)) {
++ printk("KERN_ERR reading Block %d, sector %d\n", psm->PhyBlock, psm->Sector);
++ goto error_state;
++ }
++
++ // Attempt to correct
++ switch (err = CheckECCdata(psm->SectBuf,psm->Redundant))
++ {
++ case CORRECT:
++#if DEBUG_SSFDC_WRITE
++ printk(KERN_DEBUG "ReadBlkCopy() - err == CORRECT\n");
++#endif
++ SetECCdata(psm->SectBuf,psm->Redundant);
++ case SUCCESS:
++ read_error = 0;
++ rw_retry = 0;
++ memcpy(buf + (psm->Sector * SSFDC_SECTSIZE), psm->SectBuf, SSFDC_SECTSIZE);
++ rd_sector_status[psm->Sector] = 1;
++ read_error = 0;
++ break;
++
++ case ERROR:
++error_state:
++/*bjm*/ printk("ERR - ECC error reading Block %d, Sector %d\n", psm->PhyBlock,psm->Sector);
++#if DEBUG_SSFDC_WRITE
++ printk(KERN_DEBUG "ReadBlkCopy() - err == ERROR\n");
++ printk("_ResetSsfdcErr(psm)\n");
++#endif
++ _ResetSsfdcErr(psm);
++ PrevBlock = NO_ASSIGN;
++ if (++rw_retry < RD_RETRY_LIMIT) {
++ // retry current Sector/loop counter on next loop iteration.
++ --psm->Sector;
++ }
++ else {
++ // set sector data in copy buf to the unassigned value 0xFF
++ // next loop iteration will read next Sector, zero RetryCount
++ // for next sectors read
++ // map bad sector...
++ memset(buf + psm->Sector * SSFDC_SECTSIZE, 0xFF, SSFDC_SECTSIZE);
++ rw_retry = 0;
++ rd_sector_status[psm->Sector] = 0;
++ ++psm->Sect_rd_errs_ttl;
++ read_error = 1;
++ }
++#if DEBUG_SSFDC_WRITE
++ printk(KERN_DEBUG "Unable to read Blk %d Sector %d\n", psm->PhyBlock, psm->Sector);
++#endif
++ break;
++ }
++ }
++ if (!read_error) {
++ if (SsfdcEraseBlock(psm)) {
++ MarkFailPhyOneBlock(psm);
++ ++psm->Bad_blks_erase;
++ }
++ else {
++ ClrBit(psm->Assign[psm->Zone], psm->PhyBlock);
++ }
++ }
++ else {
++ printk("Read error block %d\n", psm->PhyBlock);
++ MarkFailPhyOneBlock(psm);
++ }
++ psm->Sector = 0;
++ return read_error ? ERROR : SUCCESS;
++}
++
++/*
++ WriteBlock()
++*/
++int WriteBlock(ssfdc_dev *psm, char *buf, char *wr_sector_status)
++{
++ int write_error=0, reassign_retry=0;
++
++ for ( reassign_retry = 0; reassign_retry < REASSIGN_RETRY_LIMIT; ++reassign_retry)
++ {
++ /*
++ assign new write block for write req
++ - set new write address
++ - write buffer to new block
++ */
++#if DEBUG_SSFDC_WRITE
++ if (AssignWriteBlock(psm,1)) {
++#else
++ if (AssignWriteBlock(psm,0)) {
++#endif
++ write_error = 1;
++ printk(KERN_ERR "sm%dd Unable to assign new write block.\n", psm->sm_minor);
++ memset(wr_sector_status, 1, sizeof(char) * MAX_SECTNUM);
++ // ssfdc_terminate_request(psm, req);
++ return ERROR;
++ }
++
++#if 0
++ printk(KERN_ERR "WriteBlock() - LogBlock %d\n", psm->LogBlock);
++#endif
++
++ for (psm->Sector = 0; psm->Sector < psm->MaxSectors; ++psm->Sector)
++ {
++ memcpy(psm->SectBuf,buf+psm->Sector*SSFDC_SECTSIZE,SSFDC_SECTSIZE);
++
++ _SetSsfdcCmd(psm,SSFDC_WRDATA);
++ _SetSsfdcAddr(psm,EVEN);
++ ClrRedundantData(psm->Redundant);
++ SetLogBlockAddr(psm,psm->Redundant);
++ SetECCdata(psm->SectBuf,psm->Redundant);
++ _WriteSsfdcBuf(psm,psm->SectBuf,psm->Redundant);
++
++#if DEBUG_SSFDC_WRITE
++ printk("%d ", psm->Sector);
++#endif
++
++ _SetSsfdcCmd(psm, SSFDC_WRITE);
++ if ( ! _CheckSsfdcBusy(psm, BUSY_PROG) && !SsfdcCheckStatus(psm)) {
++#if DEBUG_SSFDC_WRITE
++ printk("\nMulti-Sector write OK!\n");
++#endif
++ _SetSsfdcStandby(psm);
++ // mark status a success
++ wr_sector_status[psm->Sector] = 1;
++
++#if 0 // bjm removed
++ { unsigned char parbuf[SSFDC_SECTSIZE];
++ unsigned char redtpar[REDTSIZE];
++
++ _SetSsfdcCmd(psm,SSFDC_READ);
++ _SetSsfdcAddr(psm, EVEN);
++
++ udelay(30);
++ if ( _HwChkBusy(psm) ) {
++ _ResetSsfdcErr(psm);
++ printk("paranoid read failure\n");
++ }
++ else {
++ _ReadSsfdcBuf(psm, parbuf, redtpar);
++ if (CheckDataStatus(redtpar)) {
++ printk("paranoid read, bad data status\n");
++ }
++ else {
++ switch( err = CheckECCdata(parbuf,redtpar))
++ {
++ case CORRECT:
++ printk("paranoid correctable\n");
++ SetECCdata(parbuf,redtpar);
++ case SUCCESS:
++ if (memcmp(parbuf,psm->SectBuf, SSFDC_SECTSIZE))
++ write_error = 1;
++ else
++ write_error = 0;
++ break;
++ case ERROR:
++ MarkFailPhyOneBlock(psm);
++ write_error=1;
++ break;
++ }
++ }
++ }
++ } // bjm end of paranoid read back test...
++#endif
++ }
++ else {
++#if DEBUG_SSFDC_WRITE
++ printk("\nMulti-Sector write FAILED!\n");
++#endif
++ // mark status a failure
++ wr_sector_status[psm->Sector] = 0;
++ _ResetSsfdcErr(psm);
++ write_error = 1;
++ break;
++ } // for (psm->Sector ...)
++ if (write_error)
++ break;
++ }
++ if ( ! write_error ) {
++ psm->Log2Phy[psm->Zone][psm->LogBlock] = psm->WriteBlock;
++ break;
++ }
++ }
++ psm->Sector = 0;
++ return write_error ? ERROR : SUCCESS;
++}
++
++/*
++ MediaWriteSector()
++
++*/
++static int MediaWriteSector(ssfdc_dev *psm, struct request *req, char * bbuf, long start, int count)
++{
++ int write_error=0, unwritten_block=0;
++ char *buf;
++ unsigned long curr_sector, blksize, PrevBlock;
++ unsigned long writebuf_index, readbio_index;
++ int i, sector, rw_retry=0;
++ int sectors_in_block;
++ char rd_sector_status[MAX_SECTNUM];
++ char wr_sector_status[MAX_SECTNUM];
++
++ // optimized write, new vars
++ int bio_endios=0;
++ int bio_bvecs=0;
++ struct bio *bio;
++ // optimized for write
++
++#if DEBUG_SSFDC_WRITE
++ printk(KERN_DEBUG "+MediaWriteSector()\n");
++#endif
++
++ if (!count) {
++ printk("MediaWriteSector() count == 0!\n");
++ ssfdc_end_request(psm, req, 0);
++ return 1;
++ }
++
++ if (CheckMediaWP(psm)) {
++ printk(KERN_DEBUG "%s: write protected media.\n", MAJOR_NAME);
++ ssfdc_terminate_request( psm, req);
++ psm->XferState = xfer_idle;
++ return -EIO;
++ }
++
++ // allocate block size buffer
++ blksize = psm->MaxSectors * SSFDC_SECTSIZE;
++#if DEBUG_SSFDC_WRITE
++ printk(KERN_DEBUG "%s: Allocate %d sized block.\n", MAJOR_NAME, blksize);
++#endif
++ if ((buf = kmalloc(blksize, GFP_ATOMIC)) == NULL) {
++ printk(KERN_ERR "%s: Null buffer allocated!\n", MAJOR_NAME);
++ ssfdc_terminate_request( psm, req);
++ goto the_exit;
++ }
++
++ /*
++ Loop to handle a request at the curr_sector of count sectors.
++ The write operation my encompas more than one phys block.
++ */
++ curr_sector = start;
++ sectors_in_block = 0;
++ // zero out our sector R/W status array
++ memset(rd_sector_status, 1, sizeof(char) * MAX_SECTNUM);
++ memset(wr_sector_status, 1, sizeof(char) * MAX_SECTNUM);
++
++ // rangecheck this sector within the device.
++ if (ConvMediaAddr(psm, curr_sector)) {
++ ssfdc_terminate_request(psm, req);
++ printk(KERN_ERR "WriteSector: ConvMediaAddr() error\n");
++#if DEBUG_SSFDC_WRITE
++ printk(KERN_DEBUG "-MediaWriteSector()\n");
++#endif
++ return 0;
++ }
++
++#if DEBUG_SSFDC_WRITE
++ printk(KERN_DEBUG "MediaWriteSector() Zone %d, LogBlock %d PhyBlock %d, Sector %d\n",
++ psm->Zone,psm->LogBlock, psm->PhyBlock,psm->Sector);
++#endif
++
++ PrevBlock = NO_ASSIGN;
++ rw_retry = 0;
++
++#if DEBUG_SSFDC_WRITE
++ printk(KERN_DEBUG "Copy Zone %d, Phys %d\n", psm->Zone, psm->PhyBlock);
++#endif
++ // As a technique for wear leveling, a write to the SM results in the contents
++ // of the block to be copied into a blocksize buffer, the write data of the
++ // write request being overlayed onto the buffer containing the copied block,
++ // a new logical to physical mapping defined, and the buffer written into this
++ // newly mapped (logically) physical block.
++
++ // read the physical block into the buffer.
++#if DEBUG_SSFDC_WRITE
++ printk(KERN_DEBUG "ReadBlock = %d LogBlock %d\n", psm->PhyBlock, psm->LogBlock);
++#endif
++ if (ReadBlkCopy(psm, buf, rd_sector_status) != SUCCESS) {
++ printk(KERN_ERR "Unable to read block.\n");
++ goto the_exit;
++ }
++
++#if DEBUG_SSFDC_WRITE
++ printk(KERN_DEBUG "Read from pending write request ");
++#endif
++
++#if 0
++ int bio_idx=0;
++#endif
++ rq_for_each_bio(bio, req) {
++ struct bio_vec *bvec;
++ int i, break_flag=0;
++#if 0
++ int segment_idx;
++ printk(KERN_ERR "bio %d\n", bio_idx++);
++
++ segment_idx = 0;
++#endif
++ // bio_bvecs = 0;
++ bio_for_each_segment(bvec, bio, i) {
++#if 0
++ printk(KERN_ERR "segment %d\n", segment_idx++);
++#endif
++ // The conditions...
++ // bio fits within block
++ if (WriteReqInCurrBlk(psm,curr_sector + (bvec->bv_len >> 9) - 1,&sector)
++ && WriteReqInCurrBlk(psm,curr_sector, &sector))
++ {
++#if 0
++ printk(KERN_ERR "LogBlk %d: write at %d, %d sectors\n",
++ psm->LogBlock, curr_sector % psm->MaxSectors, bio_cur_sectors(bio));
++#endif
++ // write bio into copied block
++ ++bio_bvecs;
++ writebuf_index = sector * SSFDC_SECTSIZE;
++#if 0
++ printk(KERN_ERR "memcpy buf at 0x%x, 0x%x bytes\n",
++ writebuf_index, bvec->bv_len);
++#endif
++ memcpy(buf + writebuf_index,
++ page_address(bvec->bv_page) + bvec->bv_offset, bvec->bv_len);
++ unwritten_block = 1;
++ curr_sector += bvec->bv_len >> 9;
++ }
++ // bio fits partially within block
++ else if (WriteReqInCurrBlk(psm,curr_sector, &sector))
++ {
++ // put portion of bio in block
++ ++bio_bvecs;
++ writebuf_index = sector * SSFDC_SECTSIZE;
++ sectors_in_block = psm->MaxSectors - sector;
++ readbio_index = sectors_in_block * SSFDC_SECTSIZE;
++#if 0
++ printk(KERN_ERR "memcpy buf at %x, %x bytes\n",
++ writebuf_index, readbio_index);
++#endif
++ memcpy(buf + writebuf_index,
++ page_address(bvec->bv_page) + bvec->bv_offset, readbio_index);
++#if 0
++ printk(KERN_ERR "LogBlk %d: partial-write at %d, %d sectors first\n",
++ psm->LogBlock, curr_sector % psm->MaxSectors, sectors_in_block);
++#endif
++ // write block
++ unwritten_block = 0;
++ if (WriteBlock(psm, buf, wr_sector_status) != SUCCESS) {
++ printk(KERN_ERR "Unable to write block %d\n", psm->LogBlock);
++ // write_error - writing this block failed
++ break_flag = 1;
++ break;
++ }
++ // incr addr & read next block,
++ curr_sector += sectors_in_block;
++ if (ConvMediaAddr(psm,curr_sector) != SUCCESS) {
++ printk(KERN_ERR "MediaWriteSector() IncMediaAddr() error!\n");
++ // write_error - address into next block is bogus
++ write_error = 1;
++ break_flag = 1;
++ break;
++ }
++ if (ReadBlkCopy(psm, buf, rd_sector_status) != SUCCESS) {
++ printk(KERN_ERR "MediaWriteSector() ReadBlkCopy() error!\n");
++ // write error - next block read error
++ write_error = 1;
++ break_flag =1;
++ break;
++ }
++ // write remainder of bio into block
++#if 0
++ printk(KERN_ERR "LogBlk %d: partial-write at %d, %d sectors, second write\n",
++ psm->LogBlock, curr_sector % psm->MaxSectors, (bvec->bv_len >> 9) - sectors_in_block);
++#endif
++#if 0
++ printk(KERN_ERR "memcpy buf at 0x%x, from bio 0x%x, for 0x%x bytes\n",
++ 0, readbio_index, ((bvec->bv_len >> 9) - sectors_in_block) * SSFDC_SECTSIZE);
++#endif
++ memcpy(buf, (page_address(bvec->bv_page) + bvec->bv_offset) + readbio_index,
++ ((bvec->bv_len >> 9) - sectors_in_block) * SSFDC_SECTSIZE);
++ writebuf_index = ((bvec->bv_len >> 9) - sectors_in_block) * SSFDC_SECTSIZE;
++ unwritten_block = 1;
++ curr_sector += (bvec->bv_len >> 9) - sectors_in_block;
++ }
++ // bio is not in block at all. coplete unwritten block and exit loop.
++ else {
++ // write current block
++#if 0
++ printk(KERN_ERR "bio no longer in block\n");
++#endif
++ if (unwritten_block) {
++ if (WriteBlock(psm, buf, wr_sector_status) != SUCCESS) {
++ printk(KERN_ERR "MediaWriteSector() WriteBlock() error!\n");
++ // write_error
++ }
++ unwritten_block = 0;
++ }
++ break_flag = 1;
++ break;
++ }
++ }
++ // bjm if (bio_bvecs) +bio_bvecs;
++
++ if (break_flag)
++ break;
++ }
++
++ if (unwritten_block) {
++ if (WriteBlock(psm, buf, wr_sector_status) != SUCCESS) {
++ printk(KERN_ERR "MediaWriteSector() WriteBlock() error!\n");
++ write_error = 1;
++ }
++ }
++
++ if (!(bio_endios=bio_bvecs)) {
++ if (static_ssfdc_debug)
++ printk("no bios from request!\n");
++ ++bio_endios;
++ write_error = 0;
++ }
++
++the_exit:
++ // log sector status for the copied/unmodified Sectors and flag any that have cpy errors
++ for (sector = 0; sector < psm->MaxSectors; ++sector) {
++ if ( ! rd_sector_status[sector] )
++ printk(KERN_ERR "%s: READ sector %d invalid for block %d!\n", \
++ MAJOR_NAME, sector, psm->LogBlock);
++ if ( ! wr_sector_status[sector])
++ printk(KERN_ERR "%s: WRITTEN sector %d invalid for block %d!\n", \
++ MAJOR_NAME, sector, psm->LogBlock);
++ }
++
++ // free our prev allocated block for copy...
++ if (buf)
++ kfree(buf);
++
++ psm->XferState = xfer_idle;
++
++#if DEBUG_SSFDC_WRITE
++ printk(KERN_DEBUG "-MediaWriteSector()\n");
++#endif
++ if (static_ssfdc_debug)
++ printk("end_request(%d) ", ! write_error);
++ for (i = 0; i < bio_endios; ++i) {
++ if (static_ssfdc_debug)
++ printk("%d ", i);
++ ssfdc_end_request(psm, req, ! write_error);
++ }
++ if (static_ssfdc_debug)
++ printk("\n");
++
++ return ! write_error;
++
++}
++
++
++/***************************************************************************
++ SmartMedia Logical Format Subroutine
++ ***************************************************************************/
++int CheckLogCHS(ssfdc_dev *psm, unsigned int *c,unsigned char *h,unsigned char *s)
++{
++ switch(psm->Model) {
++ case SSFDC1MB: *c=125; *h= 4; *s= 4; break;
++ case SSFDC2MB: *c=125; *h= 4; *s= 8; break;
++ case SSFDC4MB: *c=250; *h= 4; *s= 8; break;
++ case SSFDC8MB: *c=250; *h= 4; *s=16; break;
++ case SSFDC16MB: *c=500; *h= 4; *s=16; break;
++ case SSFDC32MB: *c=500; *h= 8; *s=16; break;
++ case SSFDC64MB: *c=500; *h= 8; *s=32; break;
++ case SSFDC128MB: *c=500; *h=16; *s=32; break;
++ default:
++ *c= 0; *h= 0; *s= 0;
++ psm->ErrCode=ERR_NoSmartMedia;
++ return(ERROR);
++ }
++ return(SUCCESS);
++}
++/***************************************************************************
++ Power Control & Media Exist Check Subroutine
++ ***************************************************************************/
++
++int CheckMediaWP(ssfdc_dev *psm)
++{
++ if(psm->Attribute &MWP)
++ { psm->ErrCode=ERR_WrtProtect; return(ERROR); }
++ return(SUCCESS);
++}
++
++/***************************************************************************
++ SmartMedia Physical Address Control Subroutine
++ ***************************************************************************/
++int ConvMediaAddr(ssfdc_dev *psm, long addr)
++{
++ long temp;
++ temp =addr/psm->MaxSectors;
++ psm->Sector =addr%psm->MaxSectors;
++ psm->LogBlock=temp%psm->MaxLogBlocks;
++ psm->Zone =temp/psm->MaxLogBlocks;
++ if(psm->Zone<psm->MaxZones) {
++ ClrRedundantData(psm->Redundant);
++ SetLogBlockAddr(psm,psm->Redundant);
++ psm->PhyBlock=psm->Log2Phy[psm->Zone][psm->LogBlock];
++#if DEBUG_SSFDC_ASSIGNRELEASE
++ printk(KERN_DEBUG "ConvMediaAddr() LogBlock %d -> PhyBlock %d\n",
++ psm->LogBlock, psm->PhyBlock);
++#endif
++ return(SUCCESS);
++ }
++ psm->ErrCode=ERR_OutOfLBA;
++ return(ERROR);
++}
++
++int IncMediaAddr(ssfdc_dev *psm)
++{
++ if(++psm->Sector<psm->MaxSectors)
++ return(SUCCESS);
++ psm->Sector=0;
++ if(++psm->LogBlock<psm->MaxLogBlocks) {
++ ClrRedundantData(psm->Redundant);
++ SetLogBlockAddr(psm,psm->Redundant);
++ psm->PhyBlock=psm->Log2Phy[psm->Zone][psm->LogBlock];
++#if DEBUG_SSFDC_ASSIGNRELEASE
++ printk(KERN_DEBUG "IncMediaAddr() PhyBlock %d <- LogBlock %d\n",
++ psm->PhyBlock, psm->LogBlock);
++#endif
++ return(SUCCESS);
++ }
++ psm->LogBlock=0;
++ if(++psm->Zone<psm->MaxZones) {
++ ClrRedundantData(psm->Redundant);
++ SetLogBlockAddr(psm,psm->Redundant);
++ psm->PhyBlock=psm->Log2Phy[psm->Zone][psm->LogBlock];
++#if DEBUG_SSFDC_ASSIGNRELEASE
++ printk(KERN_DEBUG "IncMediaAddr() PhyBlock %d <- LogBlock %d\n",
++ psm->PhyBlock, psm->LogBlock);
++#endif
++ return(SUCCESS);
++ }
++ psm->Zone=0;
++ psm->ErrCode=ERR_OutOfLBA;
++ return(ERROR);
++}
++
++/***************************************************************************/
++
++
++static int WriteReqInCurrBlk(ssfdc_dev *psm, long sector, int *blksector)
++{
++ long temp;
++ unsigned char Zone; /* Zone Number */
++ unsigned int LogBlock; /* Logical Block Number of Zone */
++
++ if (!psm)
++ return 0;
++
++ temp = sector / psm->MaxSectors;
++ *blksector = sector % psm->MaxSectors;
++ LogBlock = temp % psm->MaxLogBlocks;
++ Zone = temp / psm->MaxLogBlocks;
++
++ return (psm->LogBlock == LogBlock && psm->Zone == Zone);
++}
++
++/***************************************************************************
++ SmartMedia Read/Write Subroutine with Retry
++ ***************************************************************************/
++
++/***************************************************************************
++ SmartMedia Physical Block Assign/Release Subroutine
++ ***************************************************************************/
++int AssignWriteBlock(ssfdc_dev *psm, int verbose_flag)
++{
++ psm->ReadBlock=psm->PhyBlock;
++#if DEBUG_SSFDC_WRITE
++ int Zonesave=psm->Zone, ZoneIndex;
++#endif
++
++#if DEBUG_SSFDC_WRITE
++ if (verbose_flag) {
++ printk("AssignWriteBlock() verbose mode. psm->Zone %d\n",psm->Zone);
++ for (psm->Zone = 0; psm->Zone < psm->MaxZones; psm->Zone++) {
++ int free_blk=0;
++ printk("\tZone %d, AssignStart %d and ", psm->Zone, psm->AssignStart[psm->Zone]);
++ for (psm->WriteBlock=0; psm->WriteBlock < psm->MaxLogBlocks; psm->WriteBlock++)
++ if (! ChkBit(psm->Assign[psm->Zone],psm->WriteBlock)) ++free_blk;
++ printk("%d free blocks.\n", free_blk);
++ }
++ psm->Zone = Zonesave;
++ }
++#endif
++ for(psm->WriteBlock=psm->AssignStart[psm->Zone]; psm->WriteBlock<psm->MaxBlocks; psm->WriteBlock++)
++ if(! ChkBit(psm->Assign[psm->Zone],psm->WriteBlock)) {
++ SetBit(psm->Assign[psm->Zone],psm->WriteBlock);
++ psm->AssignStart[psm->Zone]=psm->WriteBlock+1;
++ psm->PhyBlock=psm->WriteBlock;
++ psm->SectCopyMode=REQ_ERASE;
++#if DEBUG_SSFDC_ASSIGNRELEASE
++ printk(KERN_DEBUG "AssignWriteBlock() - WriteBlock %d ReadBlock %d LogBlock %d\n",
++ psm->WriteBlock, psm->ReadBlock, psm->LogBlock);
++#endif
++ return(SUCCESS);
++ }
++ for(psm->WriteBlock=0; psm->WriteBlock<psm->AssignStart[psm->Zone]; psm->WriteBlock++)
++ if(! ChkBit(psm->Assign[psm->Zone],psm->WriteBlock)) {
++ SetBit(psm->Assign[psm->Zone],psm->WriteBlock);
++ psm->AssignStart[psm->Zone]=psm->WriteBlock+1;
++ psm->PhyBlock=psm->WriteBlock;
++ psm->SectCopyMode=REQ_ERASE;
++#if DEBUG_SSFDC_ASSIGNRELEASE
++ printk(KERN_DEBUG "AssignWriteBlock() - WriteBlock %d PhyBlock %d LogBlock %d\n",
++ psm->WriteBlock, psm->PhyBlock, psm->LogBlock);
++#endif
++ return(SUCCESS);
++ }
++ psm->WriteBlock=NO_ASSIGN;
++ psm->ErrCode=ERR_WriteFault;
++ return(ERROR);
++}
++
++/***************************************************************************
++ SmartMedia Physical Format Check Local Subroutine
++ ***************************************************************************/
++static int SetPhyFmtValue(ssfdc_dev *psm)
++{
++ unsigned int idcode;
++ SsfdcReadID(psm, &idcode);
++ if(SetSsfdcModel(psm,(unsigned char)idcode))
++ return(ERROR);
++ if(CheckSsfdcWP(psm))
++ psm->Attribute|=WP;
++ return(SUCCESS);
++}
++
++static int SearchCIS(ssfdc_dev *psm, unsigned int *pcis)
++{
++ psm->Zone=0; psm->Sector=0;
++ for(psm->PhyBlock=0; psm->PhyBlock<(psm->MaxBlocks-psm->MaxLogBlocks-1); psm->PhyBlock++) {
++ if(SsfdcReadRedtData(psm, psm->Redundant))
++ { SsfdcReset(psm); return(ERROR); }
++ if(! CheckFailBlock(psm->Redundant)) {
++ if(CheckCisBlock(psm->Redundant))
++ { SsfdcReset(psm); return(ERROR); }
++ break;
++ }
++ }
++ while(psm->Sector<psm->MaxSectors) {
++ if(psm->Sector)
++ if(SsfdcReadRedtData(psm, psm->Redundant))
++ { SsfdcReset(psm); return(ERROR); }
++ if(! CheckDataStatus(psm->Redundant)) {
++ if(SsfdcReadSect(psm,psm->WorkBuf,psm->Redundant))
++ { SsfdcReset(psm); return(ERROR); }
++ if(CheckCISdata(psm->WorkBuf,psm->Redundant))
++ { SsfdcReset(psm); return(ERROR); }
++ *pcis=psm->PhyBlock;
++ SsfdcReset(psm);
++ return(SUCCESS);
++ }
++ psm->Sector++;
++ }
++ SsfdcReset(psm);
++ return(ERROR);
++}
++
++/***************************************************************************/
++static int MakeLogTable(ssfdc_dev *psm, unsigned int start)
++{
++ unsigned int block;
++ unsigned int blk_total=0, blk_blank=0, blk_nologaddr=0,
++ blk_fail=0, blk_assigned=0;
++
++#if DEBUG_SSFDC
++ printk(KERN_DEBUG "MakeLogTable()\n");
++#endif
++ psm->DataBuf_Valid = 1;
++ psm->Sector=0;
++ for(psm->Zone=0; psm->Zone<psm->MaxZones; psm->Zone++) {
++ /* set all LogBlocks to NO_ASSIGN */
++ for(psm->LogBlock=0; psm->LogBlock<psm->MaxLogBlocks; psm->LogBlock++)
++ psm->Log2Phy[psm->Zone][psm->LogBlock]=NO_ASSIGN;
++ /* for all Assigns[zone][PhyBlock] = 0x00 */
++ for(psm->PhyBlock=0; psm->PhyBlock<(MAX_BLOCKNUM/8); psm->PhyBlock++)
++ psm->Assign[psm->Zone][psm->PhyBlock]=0x00;
++ /*******************************************************************/
++ for(psm->PhyBlock=0; psm->PhyBlock<psm->MaxBlocks; psm->PhyBlock++) {
++ if((! psm->Zone) && (psm->PhyBlock<start)) {
++ SetBit(psm->Assign[psm->Zone],psm->PhyBlock);
++ continue;
++ }
++ ++blk_total;
++ if(SsfdcReadRedtData(psm,psm->Redundant)) {
++ SsfdcReset(psm);
++#if 0
++ printk(KERN_ERR "error 1 PhyBlock %d\n", psm->PhyBlock);
++#endif
++ return(ERROR);
++ }
++ if(! CheckDataBlank(psm->Redundant)) {
++ ++blk_blank;
++ continue;
++ }
++ SetBit(psm->Assign[psm->Zone],psm->PhyBlock);
++ if(CheckFailBlock(psm->Redundant)) {
++#if 0
++ printk("Zone %d, Block %d failed\n", psm->Zone, psm->PhyBlock);
++#endif
++ ++blk_fail;
++ continue;
++ }
++ if(LoadLogBlockAddr(psm)) {
++ ++blk_nologaddr;
++ continue;
++ }
++ if(psm->LogBlock>=psm->MaxLogBlocks)
++ continue;
++ ++blk_assigned;
++ if(psm->Log2Phy[psm->Zone][psm->LogBlock]==NO_ASSIGN) {
++#if DEBUG_SSFDC_ASSIGNRELEASE
++ if (psm->LogBlock == 0)
++ printk(KERN_DEBUG "MakeLogTable() LogBlock %d = PhyBlock %d\n",
++ psm->LogBlock, psm->PhyBlock);
++#endif
++ psm->Log2Phy[psm->Zone][psm->LogBlock]=psm->PhyBlock;
++ continue;
++ }
++ psm->Sector=psm->MaxSectors-1;
++ if(SsfdcReadRedtData(psm,psm->Redundant)) {
++ SsfdcReset(psm);
++#if 0
++ printk(KERN_ERR "error 2\n");
++#endif
++ return(ERROR);
++ }
++ psm->Sector=0;
++ block=psm->LogBlock;
++ if(! LoadLogBlockAddr(psm))
++ if(psm->LogBlock==block) {
++#ifdef L2P_ERR_ERASE /***************************************************/
++ block=psm->Log2Phy[psm->Zone][psm->LogBlock];
++ psm->Log2Phy[psm->Zone][psm->LogBlock]=psm->PhyBlock;
++ psm->PhyBlock=block;
++ if(!(psm->Attribute &MWP)) {
++ SsfdcReset(psm);
++ if(SsfdcEraseBlock(psm)) {
++ printk(KERN_ERR "error 3\n");
++ return(ERROR);
++ }
++ if(SsfdcCheckStatus(psm)) {
++ if(MarkFailPhyOneBlock(psm)) {
++ printk(KERN_ERR "error 4\n");
++ return(ERROR);
++ }
++ }
++ else ClrBit(psm->Assign[psm->Zone],psm->PhyBlock);
++ }
++ psm->PhyBlock=psm->Log2Phy[psm->Zone][psm->LogBlock];
++#else /*******************************************************************/
++ psm->Log2Phy[psm->Zone][psm->LogBlock]=psm->PhyBlock;
++#endif /*******************************************************************/
++ continue;
++ }
++#ifdef L2P_ERR_ERASE /***************************************************/
++ if(!(psm->Attribute &MWP)) {
++ SsfdcReset(psm);
++ if(SsfdcEraseBlock(psm)) {
++ printk(KERN_ERR "error 5\n");
++ return(ERROR);
++ }
++ if(SsfdcCheckStatus(psm)) {
++ if(MarkFailPhyOneBlock(psm)) {
++ printk(KERN_ERR "error 6\n");
++ return(ERROR);
++ }
++ }
++ else ClrBit(psm->Assign[psm->Zone],psm->PhyBlock);
++ }
++#endif /*******************************************************************/
++ }
++ psm->AssignStart[psm->Zone]=0;
++ }
++ SsfdcReset(psm);
++#if 0
++ printk("MakeLogTable()\n");
++ printk("\t%d failed\n", blk_fail);
++ printk("\t%d blank\n", blk_blank);
++ printk("\t%d assigned\n", blk_assigned);
++ printk("\t%d no logical addr\n", blk_nologaddr);
++ printk("\n\t%d total\n", blk_total);
++ printk("\t%d sum total\n", blk_fail + blk_blank + blk_assigned + blk_nologaddr);
++#endif
++ return(SUCCESS);
++}
++
++/***************************************************************************/
++static int MarkFailPhyOneBlock(ssfdc_dev *psm)
++{
++ unsigned char sect;
++ sect=psm->Sector;
++ SetFailBlock(psm->WorkRedund);
++ SsfdcWriteRedtMode(psm);
++ for(psm->Sector=0; psm->Sector<psm->MaxSectors; psm->Sector++)
++ if(SsfdcWriteRedtData(psm,psm->WorkRedund)) {
++ SsfdcReset(psm);
++ psm->Sector=sect;
++ psm->ErrCode=ERR_HwError;
++ return(ERROR);
++ } /* NO Status Check */
++ SsfdcReset(psm);
++ psm->Sector=sect;
++ return(SUCCESS);
++}
++
++/***************************************************************************
++ SmartMedia Control subroutine
++ Rev 0.30('98-06-30) ***** BETA RELEASE *****
++ Copyright (c) 1997-98, Toshiba Corporation. All rights reserved.
++ ***************************************************************************/
++
++
++/* Linux Driver Modifications */
++/*
++dump_ssfdc_state
++*/
++#if DEBUG_SSFDC
++void dump_ssfdc_state(ssfdc_dev * psm)
++{
++#if DEBUG_SSFDC_STRUCT
++ // misc structure dump information
++ printk(KERN_DEBUG "psm->\n");
++ /* unsigned long */ printk(KERN_DEBUG "\t address %x\n", psm->address);
++ /* int */ printk(KERN_DEBUG "\t sm_minor %d\n",psm->sm_minor);
++ /* struct dentry printk(KERN_DEBUG "\t *sm_dentry %x\n",psm->sm_dentry );*/
++ /* kdev_t */ printk(KERN_DEBUG "\t sm_device %x\n",psm->sm_device);
++ /* int */ printk(KERN_DEBUG "\t sm_flags %x\n",psm->sm_flags);
++ /* unsigned int */ printk(KERN_DEBUG "\t UseCount %d\n",psm->UseCount);
++ /* unsigned int */ printk(KERN_DEBUG "\t ErrCode %d\n",psm->ErrCode);
++ /* unsigned int */ printk(KERN_DEBUG "\t MediaChange %d\n",psm->MediaChange);
++ /* unsigned int */ printk(KERN_DEBUG "\t SectCopyMode %d\n",psm->SectCopyMode);
++ /* unsigned int */ printk(KERN_DEBUG "\t HostCyl %d\n",psm->HostCyl );
++ /* unsigned char */ printk(KERN_DEBUG "\t HostHead %d\n",psm->HostHead );
++ /* unsigned char */ printk(KERN_DEBUG "\t HostSect %d\n",psm->HostSect );
++ /* unsigned int */ printk(KERN_DEBUG "\t ReadBlock %d\n",psm->ReadBlock );
++ /* unsigned int */ printk(KERN_DEBUG "\t WriteBlock %d\n",psm->WriteBlock );
++
++ /* Card attributes */
++ /* unsigned char */ printk(KERN_DEBUG "\t Model %d\n",psm->Model );
++ /* unsigned char */ printk(KERN_DEBUG "\t Attribute %x\n",psm->Attribute );
++ /* unsigned char */ printk(KERN_DEBUG "\t MaxZones %d\n",psm->MaxZones );
++ /* unsigned char */ printk(KERN_DEBUG "\t MaxSectors %d\n",psm->MaxSectors );
++ /* unsigned int */ printk(KERN_DEBUG "\t MaxBlocks %d\n",psm->MaxBlocks );
++ /* unsigned int */ printk(KERN_DEBUG "\t MaxLogBlocks %d\n",psm->MaxLogBlocks );
++ /* unsigned char */ printk(KERN_DEBUG "\t Zone %d\n",psm->Zone );
++ /* unsigned char */ printk(KERN_DEBUG "\t Sector %d\n",psm->Sector );
++ /* unsigned int */ printk(KERN_DEBUG "\t PhyBlock %d\n",psm->PhyBlock );
++ /* unsigned int */ printk(KERN_DEBUG "\t LogBlock %d\n",psm->LogBlock );
++#endif
++}
++#endif
++
++typedef struct {
++ int sm_error;
++ int lnx_error;
++ char *smerrstr;
++} errmap;
++
++static errmap error_map_table [] = {
++ { NO_ERROR, 0x0000, ""},
++ { ERR_WriteFault, EIO, "Peripheral Device Write Fault "},
++ { ERR_HwError, EIO, "Hardware Error"},
++ { ERR_DataStatus, EIO, "DataStatus Error"},
++ { ERR_EccReadErr, EIO, "Unrecovered Read Error" },
++ { ERR_CorReadErr, EIO, "Recovered Read Data with ECC" },
++ { ERR_OutOfLBA, EIO, "Illegal Logical Block Address" },
++ { ERR_WrtProtect, EROFS, "Write Protected" },
++ { ERR_ChangedMedia, EIO, "Medium Changed" },
++ { ERR_UnknownMedia, EIO, "Incompatible Medium Installed" },
++ { ERR_IllegalFmt, EIO, "Medium Format Corrupted" },
++ { ERR_NoSmartMedia, EIO, "Medium Not Present" }
++};
++
++static int ssfdc_maperror(int ssfdc_error) {
++ int loopus=0;
++
++ if (!ssfdc_error) return 0;
++
++ do {
++ if (error_map_table[loopus].sm_error == ssfdc_error) {
++ printk("%s\n", error_map_table[loopus].smerrstr);
++ return -error_map_table[loopus].lnx_error;
++ }
++ } while (++loopus < (sizeof(error_map_table) / (sizeof(errmap))));
++
++ printk(KERN_ERR "%s: error code %d is not mapped, EIO\n", MAJOR_NAME, ssfdc_error);
++ return -EIO;
++}
++
++static int ssfdc_thread(void * arg)
++{
++ ssfdc_dev *psm = arg;
++ unsigned long flags;
++
++ daemonize("sm%dd",psm->sm_minor);
++
++ spin_lock_irqsave(&current->sighand->siglock,flags); // _irq
++ sigfillset(&current->blocked);
++ recalc_sigpending();
++ spin_unlock_irqrestore(&current->sighand->siglock,flags); // _irq
++
++ while (!psm->exiting) {
++ if ( ssfdc_get_request(psm) )
++ initxfer(psm->sm_minor);
++
++ spin_lock_irqsave(&psm->req_queue_lock,flags); // _irq
++ // bjm spin_lock(&psm->req_queue_lock); // _irq
++ psm->waiting = 0;
++ spin_unlock_irqrestore(&psm->req_queue_lock,flags); // _irq
++ // bjm spin_unlock(&psm->req_queue_lock); // _irq
++ if (wait_event_interruptible(psm->thread_wq,ssfdc_get_request(psm)))
++ printk("ssfdc_thread() interrupted\n");
++ // wait_event(psm->thread_wq,ssfdc_get_request(psm));
++ spin_lock_irqsave(&psm->req_queue_lock,flags); // _irq
++ // bjm spin_lock(&psm->req_queue_lock); // _irq
++ psm->waiting = 1;
++ spin_unlock_irqrestore(&psm->req_queue_lock,flags); // _irq
++ // bjm spin_unlock(&psm->req_queue_lock); // _irq
++ }
++
++ printk("ssfdcd Exiting!\n");
++
++ complete_and_exit(&psm->thread_dead, 0);
++
++}
++
++/*
++ssfdc_init_device(ssfdc_dev *, int minor, unsigned long baseaddr, int removable)
++ reset and initialize the ssfdc_dev structure
++*/
++static int ssfdc_init_device(ssfdc_dev *psm, int minor, unsigned long baseaddr)
++{
++ int pid;
++
++ // Establish ssfdc state
++ psm->XferState = xfer_idle;
++ psm->ErrCode = NO_ERROR;
++ psm->MediaChange = SUCCESS;
++ psm->SectCopyMode = COMPLETED;
++ psm->UseCount = 0;
++ psm->DataBuf_Valid = 0;
++
++ // set minor number
++ psm->sm_minor = minor;
++ // io address
++ psm->address = baseaddr;
++ if (!request_region(psm->address, 3, "sm")) {
++ printk(KERN_ERR "sm: memory already in use!\n");
++ return ERROR;
++ }
++ spin_lock_init(&psm->req_queue_lock);
++
++ // thread related inititializations...
++ init_completion(&psm->thread_dead);
++ init_waitqueue_head(&psm->thread_wq);
++
++ pid = kernel_thread(ssfdc_thread, psm, CLONE_KERNEL);
++ if (pid < 0)
++ printk("ssfdc: ERROR starting thread!\n");
++ else
++ printk("ssfdc: started kernel thread sm%dd pid %d\n", psm->sm_minor, pid);
++
++ // switch on power to device, and set basic attributes of card (no logical to phys mapping)
++ if ( ! CntPowerOn(psm) && ! CheckCardExist(psm) ) {
++ SetPhyFmtValue(psm);
++ }
++ else {
++ printk(KERN_ERR "ssfdc_init_device() unable to SetPhyFmtValue()\n");
++ }
++
++#if DEBUG_SSFDC
++ dump_ssfdc_state(psm);
++#endif
++
++ return SUCCESS;
++}
++
++static int ssfdc_dev_blk_size(ssfdc_dev *psm)
++{
++ if (!psm)
++ return 0;
++
++ // because of the physical to logical block mapping, not as many blocks
++ // as expected...
++ switch(psm->Model) {
++ case SSFDC1MB:
++ return (250 * 8 * 512) / SSFDC_BLKSIZE;
++ case SSFDC2MB:
++ return (500 * 8 * 512) / SSFDC_BLKSIZE;
++ case SSFDC4MB:
++ return (500 * 16 * 512) / SSFDC_BLKSIZE;
++ case SSFDC8MB:
++ return (1000 * 16 * 512) / SSFDC_BLKSIZE;
++ case SSFDC16MB:
++ return (1000 * 32 * 512) / SSFDC_BLKSIZE;
++ case SSFDC32MB:
++ return (2000 * 32 * 512) / SSFDC_BLKSIZE;
++ case SSFDC64MB:
++ return (4000 * 32 * 512) / SSFDC_BLKSIZE;
++ case SSFDC128MB:
++ return (8000 * 32 * 512) / SSFDC_BLKSIZE;
++ default:
++ return 0;
++ }
++}
++
++inline int ssfdc_dev_sectors(ssfdc_dev *psm) {
++ return ssfdc_dev_blk_size(psm) * (SSFDC_BLKSIZE/SSFDC_SECTSIZE);
++}
++
++static int ssfdc_open(struct inode *in, struct file *fptr)
++{
++ int error_code=NO_ERROR;
++ ssfdc_dev *psm = in->i_bdev->bd_disk->private_data;
++ unsigned long flags;
++
++#if DEBUG_SSFDC
++ printk(KERN_DEBUG "+ssfdc_open()\n");
++#endif
++
++ if (!fptr) {
++ return -EIO;
++ }
++
++ spin_lock_irqsave(&psm->req_queue_lock,flags);
++ // bjm spin_lock(&psm->req_queue_lock);
++ // Power up smartmedia device, check for card, check media
++ if ((error_code=CntPowerOn(psm))) {
++ printk(KERN_ERR "%s PowerUP error\n", MAJOR_NAME);
++ }
++ else if ((error_code=CheckCardExist(psm))) {// Check the existence of a card
++ printk(KERN_ERR "%s No Card!\n", MAJOR_NAME);
++ }
++ else if ( ! psm->UseCount++ ) {
++ spin_unlock_irqrestore(&psm->req_queue_lock,flags);
++ // bjm spin_unlock(&psm->req_queue_lock);
++ check_disk_change(in->i_bdev);
++ spin_lock_irqsave(&psm->req_queue_lock,flags);
++ // bjm spin_lock(&psm->req_queue_lock);
++ }
++
++ if ( ! psm->ErrCode ) {
++ // check our open mode against that of removable media's
++ if (WRITE_PROTECTED(psm)) {
++ printk(KERN_ERR "mount read only detected.\n");
++ }
++ }
++
++#if DEBUG_SSFDC
++ dump_ssfdc_state(psm);
++ printk(KERN_DEBUG "-ssfdc_open() error_code %d\n", error_code);
++#endif
++
++ spin_unlock_irqrestore(&psm->req_queue_lock,flags);
++
++#if DEBUG_SSFDC
++ printk("-ssfdc_open()\n");
++#endif
++
++ return ssfdc_maperror(error_code);
++}
++
++static int ssfdc_release(struct inode *i_node, struct file *fptr)
++{
++ int drive;
++ ssfdc_dev *psm=NULL;
++ unsigned long flags;
++
++#if DEBUG_SSFDC
++ printk(KERN_DEBUG "+ssfdc_release(");
++#endif
++
++ psm = (ssfdc_dev *) i_node->i_bdev->bd_disk->private_data;
++ drive = psm->sm_minor;
++
++#if DEBUG_SSFDC
++ printk(KERN_DEBUG "%d)\n", drive);
++#endif
++ if (drive < 0 || drive >= MAX_SSFDC)
++ return -ENODEV;
++
++ spin_lock_irqsave(&psm->req_queue_lock,flags);
++ // bjm spin_lock(&psm->req_queue_lock);
++
++ if (!psm->UseCount)
++ printk(KERN_ERR "sm: Zero use count!\n");
++ else {
++ --psm->UseCount;
++ }
++
++#if DEBUG_SSFDC
++ dump_ssfdc_state(psm);
++#endif
++
++#if DEBUG_SSFDC
++ printk(KERN_DEBUG "-ssfdc_release()\n");
++#endif
++
++ spin_unlock_irqrestore(&psm->req_queue_lock,flags);
++ // bjm spin_unlock(&psm->req_queue_lock);
++
++ return 0;
++}
++
++static int ssfdc_ioctl(struct inode *i_node, struct file *fptr, unsigned cmd, unsigned long arg)
++{
++ int err, drive, int_val;
++ unsigned char heads, sectors;
++ unsigned int cylinders;
++ struct hd_geometry geo;
++ ssfdc_dev *psm;
++
++#if DEBUG_SSFDC
++ printk(KERN_DEBUG "ssfdc_ioctl(%d)", cmd);
++#endif
++
++ if (i_node == NULL)
++ return -EINVAL;
++
++ psm = (ssfdc_dev *) i_node->i_bdev->bd_disk->private_data;
++ drive = psm->sm_minor;
++
++ if (drive < 0 || drive >= MAX_SSFDC)
++ return -ENODEV;
++ switch(cmd) {
++ case BLKROSET: /* set device read-only (0 = read-write) */
++ if (!capable(CAP_SYS_ADMIN))
++ return -EACCES;
++ if (copy_from_user((void *) &int_val, (int *)arg, sizeof(int_val)))
++ return -EFAULT;
++ if (int_val)
++ psm->Attribute |= MWP;
++ else
++ psm->Attribute &= ~MWP;
++ return 0;
++
++ case BLKROGET:/* get read-only status (0 = read_write) */
++ int_val = psm->Attribute & MWP;
++ copy_to_user(arg, (void *) &int_val, sizeof(int_val));
++ return 0;
++
++ /* case BLKRRPART: */ /* re-read partition table */
++
++ case BLKGETSIZE:
++#if DEBUG_SSFDC
++ printk(KERN_DEBUG "BLKGETSIZE");
++#else
++ printk(KERN_DEBUG "ssfdc_ioctl(BLKGETSIZE) not handled.\n");
++#endif
++ break;
++
++ case HDIO_GETGEO:
++ if ((void *) arg == NULL) return -EINVAL;
++ if (!access_ok(VERIFY_WRITE, arg, sizeof(geo)))
++ return -EFAULT;
++ if ((err=CheckLogCHS( psm, &cylinders, &heads, &sectors)))
++ return ssfdc_maperror(err);
++ memset(&geo, 0, sizeof(geo));
++ geo.cylinders = cylinders;
++ geo.heads = heads;
++ geo.sectors = sectors;
++ geo.start = get_start_sect(i_node->i_bdev);
++ if (copy_to_user((void *) arg, &geo, sizeof(geo)))
++ return -EFAULT;
++ if (copy_to_user((void *) arg, &geo, sizeof(geo)))
++ return -EFAULT;
++ return 0;
++ }
++ return -EINVAL;
++}
++
++
++
++static int ssfdc_revalidate(struct gendisk *disk)
++{
++ unsigned int cis;
++ ssfdc_dev *psm=NULL;
++ int error_code=NO_ERROR;
++ unsigned long flags;
++
++#if DEBUG_SSFDC
++ printk(KERN_DEBUG "ssfdc_revalidate()\n");
++#endif
++
++ psm = disk->private_data;
++
++ spin_lock_irqsave(&psm->req_queue_lock,flags);
++ // bjm spin_lock(&psm->req_queue_lock);
++
++ if ( ! psm->DataBuf_Valid ) {
++ if ((error_code=SetPhyFmtValue(psm)))
++ printk(KERN_ERR "ssfdc_revalidate() SetPhyFmtValue error\n");
++ else if ((error_code=SearchCIS(psm,&cis)))
++ printk(KERN_ERR "ssfdc_revalidate() SearchCIS error\n");
++ else if ((error_code=MakeLogTable(psm,cis+1)))
++ printk(KERN_ERR "ssfdc_revalidate() MakeLogTable error\n");
++ }
++ spin_unlock_irqrestore(&psm->req_queue_lock,flags);
++ // bjm spin_unlock(&psm->req_queue_lock);
++
++ return ssfdc_maperror(error_code);
++}
++
++int __init ssfdc_init(void)
++{
++ int i;
++ int err = 0;
++
++#if DEBUG_SSFDC
++ printk(KERN_DEBUG "+ssfdc_init()\n");
++#endif
++
++ memset(disks, 0, sizeof(struct gendisk *) * MAX_SSFDC);
++ memset(ssfdc, 0, sizeof(struct ssfdc_dev *) * MAX_SSFDC);
++ for (i=0; i<MAX_SSFDC; ++i) {
++ disks[i] = alloc_disk(1 << SSFDC_PARTN_BITS);
++ ssfdc[i] = kmalloc(sizeof(ssfdc_dev), GFP_KERNEL);
++ if (!disks[i] || !ssfdc[i]) {
++ err = -ENOMEM;
++ goto no_memory_error;
++ }
++ memset( ssfdc[i], 0, sizeof(ssfdc_dev));
++ }
++
++ if (register_blkdev(SSFDC_MAJOR, "smartmedia")) {
++ printk(KERN_ERR "Unable to get major number %d for ssfdc device\n",
++ SSFDC_MAJOR);
++ err = -EBUSY;
++ goto busy_error;
++ }
++
++ devfs_mk_dir("sm");
++
++ for ( i=0; i < MAX_SSFDC; ++i) {
++ disks[i]->major = SSFDC_MAJOR;
++ disks[i]->first_minor = i << SSFDC_PARTN_BITS;
++ disks[i]->fops = &ssfdc_fops;
++ sprintf(disks[i]->disk_name, "sm%d", i);
++ sprintf(disks[i]->devfs_name, "sm/%d", i);
++ disks[i]->private_data = ssfdc[i];
++ ssfdc_init_device(ssfdc[i], i << SSFDC_PARTN_BITS,
++ CPLD_BASE_ADDRESS + SMART_MEDIA_ONE_OFFSET);
++
++ disks[i]->queue = ssfdc[i]->req_queue =
++ blk_init_queue(do_ssfdc_request, &ssfdc[i]->req_queue_lock);
++ ssfdc[i]->req_queue->queuedata = ssfdc[i];
++
++ set_capacity(disks[i], ssfdc_dev_sectors(ssfdc[i]));
++ // bjm blk_queue_max_sectors(disks[i]->queue, 32);
++ // bjm blk_queue_max_phys_segments(disks[i]->queue, 4);
++ blk_queue_max_segment_size(disks[i]->queue, (ssfdc[i]->MaxSectors / 2) * K_BYTE);
++ add_disk(disks[i]);
++ }
++
++#if 0 // bjm debug
++#ifndef CONFIG_SH_NIMBLE_MINI
++ mediachangetest(0L);
++#else
++ mediachangetest(1L);
++#endif
++#endif // bjm debug
++
++#if DEBUG_SSFDC
++ printk(KERN_DEBUG "-ssfdc_init(0)\n");
++#endif
++ return 0;
++
++busy_error:
++no_memory_error:
++ for (i=0; i < MAX_SSFDC; ++i) {
++ if (disks[i] && disks[i]->queue)
++ kfree(disks[i]->queue);
++ put_disk(disks[i]);
++ if (ssfdc[i])
++ kfree(ssfdc[i]);
++ }
++#if DEBUG_SSFDC
++ printk(KERN_DEBUG "-ssfdc_init(%d)\n", -ENOMEM);
++#endif
++ return -ENOMEM;
++}
++
++void __init ssfdc_clean(void)
++{
++ int i;
++
++ printk(KERN_DEBUG "SSFDC exit code\n");
++
++ for (i=0; i < MAX_SSFDC; ++i) {
++ if (disks[i] != NULL) {
++ blk_cleanup_queue(disks[i]->queue);
++ del_gendisk(disks[i]);
++ put_disk(disks[i]);
++ }
++
++ if (ssfdc[i]) {
++ // signal thread to exit...
++ ssfdc[i]->exiting = 1;
++ wake_up(&ssfdc[i]->thread_wq);
++ wait_for_completion(&ssfdc[i]->thread_dead);
++
++ if (ssfdc[i]->address)
++ release_region(ssfdc[i]->address, 3);
++ kfree(ssfdc[i]);
++ }
++ }
++
++ if (unregister_blkdev(SSFDC_MAJOR, "smartmedia"))
++ printk(KERN_WARNING "smartmedia: cannot unregister blkdev\n");
++ devfs_remove("sm");
++}
++
++#if DEBUG_SSFDC
++void dump_request(struct request *req)
++{
++#if DEBUG_SSFDC_REQUEST && DEBUG_SSFDC_REQUEST
++ printk(KERN_DEBUG "req->\n");
++ /* int */ printk(KERN_DEBUG "\t req->cmd %x\n", req->cmd); /* READ or WRITE */
++ /* int errors */ printk(KERN_DEBUG "\t req->errors %d\n", req->errors);
++ /* unsigned long */ printk(KERN_DEBUG "\t req->sector %d\n", req->sector);
++ /* unsigned long */ printk(KERN_DEBUG "\t req->nr_sectors %d\n",req->nr_sectors);
++ /* unsigned long */ printk(KERN_DEBUG "\t req->hard_sector %d\n", req->hard_sector);
++ /* unsigned int */ printk(KERN_DEBUG "\t req->nr_hw_segments %d\n",req->nr_hw_segments);
++ /* unsigned long */ printk(KERN_DEBUG "\t req->current_nr_sectors %d\n",req->current_nr_sectors);
++
++#endif
++}
++#endif
++
++void do_ssfdc_request(request_queue_t * rq)
++{
++ ssfdc_dev *psm = rq->queuedata;
++
++ if ( ! psm->waiting )
++ wake_up(&psm->thread_wq);
++}
++
++static struct request * ssfdc_get_request(ssfdc_dev *psm)
++{
++ struct request *treq;
++ unsigned long flags;
++
++ spin_lock_irqsave(&psm->req_queue_lock, flags);
++ // bjm spin_lock(&psm->req_queue_lock);
++ treq = elv_next_request(psm->req_queue);
++ spin_unlock_irqrestore(&psm->req_queue_lock, flags);
++ // bjm spin_unlock(&psm->req_queue_lock);
++
++ return treq;
++}
++
++static void ssfdc_terminate_request(ssfdc_dev *psm, struct request *req)
++{
++ unsigned long flags;
++
++ if (psm && req) {
++ spin_lock_irqsave(&psm->req_queue_lock, flags);
++ // bjm spin_lock(&psm->req_queue_lock);
++ end_request(req,0);
++ spin_unlock_irqrestore(&psm->req_queue_lock, flags);
++ // bjm spin_unlock(&psm->req_queue_lock);
++ }
++}
++
++
++static int ssfdc_end_request(ssfdc_dev *psm, struct request *req, int status)
++{
++ unsigned long flags;
++
++ if (!psm || !req) {
++ printk(KERN_DEBUG "ssfdc_end_request() NULL psm or req!\n");
++ return 0;
++ }
++
++#if DEBUG_SSFDC_REQUEST
++ printk("ssfdc_end_request(%p)\n", req);
++#endif
++
++ spin_lock_irqsave(&psm->req_queue_lock,flags);
++ // bjm spin_lock(&psm->req_queue_lock);
++ end_request(req,status);
++ spin_unlock_irqrestore(&psm->req_queue_lock,flags);
++ // bjm spin_unlock(&psm->req_queue_lock);
++ return 0;
++}
++
++void initxfer(unsigned long dev_idx)
++{
++ ssfdc_dev *psm = ssfdc[dev_idx];
++ struct request *req;
++ int error_code;
++ unsigned int cis;
++
++#if DEBUG_SSFDC
++ // printk(KERN_DEBUG "+initxfer(%d)", dev_idx);
++#endif
++ // get device lock, and check idle flag, setting if not busy
++
++ req = ssfdc_get_request(psm);
++
++ // if the device is idle, setup a read or write operation
++ if (psm->XferState == xfer_idle) {
++ // get the current request from our device's request list.
++ if (!req) {
++#if DEBUG_SSFDC
++// printk(KERN_DEBUG "initxfer() terminate, no schedule.\n");
++#endif
++ }
++ // Absence of power indicates absence of card.
++ // terminate request and exit...
++ if ( ! _HwChkPower(psm) ) {
++ printk(KERN_DEBUG "initxfer() - Media power NOT!\n");
++ ssfdc_terminate_request(psm,req);
++ return;
++ }
++
++ // We have a request and we have a card. Is the Log2Phys mapping still valid?
++ if ( ! psm->DataBuf_Valid ) {
++ if ((error_code = SetPhyFmtValue(psm)))
++ printk(KERN_DEBUG "%s SetPhyFmtValue error\n", MAJOR_NAME);
++ else if ((error_code = SearchCIS(psm,&cis)))
++ printk(KERN_DEBUG "%s SearchCIS error\n", MAJOR_NAME);
++ else if ((error_code = MakeLogTable(psm,cis+1)))
++ printk(KERN_DEBUG "%s MakeLogTable error\n", MAJOR_NAME);
++ if (error_code) {
++ printk(KERN_DEBUG "%s error %d\n", MAJOR_NAME, error_code);
++ ssfdc_terminate_request(psm,req);
++ return;
++ }
++ }
++
++ psm->XferState = xfer_busy;
++#if DEBUG_SSFDC
++ printk(KERN_DEBUG " initxfer() - do the request %x\n", req);
++#endif
++ ssfdc_rw_request(psm, req);
++ }
++#if DEBUG_SSFDC
++ else {
++ printk(KERN_DEBUG "initxfer(%d) dev is busy, no reschedule.\n", dev_idx);
++ }
++#endif
++
++}
++
++
++void ssfdc_rw_request(ssfdc_dev *psm, struct request *req)
++{
++ int (*rwsector)(ssfdc_dev *, struct request *, char *, long, int);
++ unsigned sector, count;
++ int rw_return=1;
++
++ if (rq_data_dir(req) == WRITE)
++ rwsector = MediaWriteSector;
++ else if (rq_data_dir(req) == READ)
++ rwsector = MediaReadSector;
++ else {
++ printk(KERN_DEBUG "%s: command %d not implemented!\n", MAJOR_NAME, (int) rq_data_dir(req));
++ goto terminal_error;
++ }
++
++ /*
++ */
++ sector = req->sector;
++ count = req->nr_sectors;
++
++ // check that the request does not extend past ssfdc's max size
++ if ( (sector + count) > ssfdc_dev_sectors(psm) ) {
++ printk(KERN_ERR "Attempt to read past end of device!");
++ goto terminal_error;
++ }
++ else {
++
++ // for each segment in each bio_vec R/W from/to device.
++
++ count = req->current_nr_sectors;
++ rw_return = rwsector(psm, req, req->buffer, sector, count);
++
++ if (rq_data_dir(req) == READ)
++ ssfdc_end_request(psm, req, rw_return);
++ }
++
++ // things appear OK...
++ return;
++
++terminal_error:
++ ssfdc_terminate_request( psm, req);
++ psm->XferState = xfer_idle;
++}
++
++module_init(ssfdc_init);
++module_exit(ssfdc_clean);
++
++MODULE_LICENSE("GPL");
++
++/* End of Linux Driver Modifications */
+diff -durN -X ../diff.ignore linux/drivers/block/ssfdc.h gcc3.4.4/drivers/block/ssfdc.h
+--- linux/drivers/block/ssfdc.h 1970-01-01 10:00:00.000000000 +1000
++++ gcc3.4.4/drivers/block/ssfdc.h 2005-11-09 14:00:47.000000000 +1100
+@@ -0,0 +1,372 @@
++/* $id: $ */
++#ifndef _SSFDC_H
++#define _SSFDC_H
++
++/*
++ Linux related defines
++*/
++
++#ifdef CONFIG_SH_NIMBLE_MINI
++#define MAX_SSFDC 2 /* two drives */
++#else
++#define MAX_SSFDC 1 /* only one drive */
++#endif
++
++#define SSFDC_MAJOR_NAME "sm"
++#define MAJOR_NAME SSFDC_MAJOR_NAME
++#define SSFDC_PARTN_BITS 4 /* number of minor dev bits for partitions */
++#define PARTN_MASK ((1<<SSFDC_PARTN_BITS)-1) /* a useful bit mask */
++#define MAX_DRIVES MAX_SSFDC
++
++/***************************************************************************
++ SmartMedia Controll Header
++ Rev 0.30('98-06-30) ***** BETA RELEASE *****
++ Copyright (c) 1997-98, Toshiba Corporation. All rights reserved.
++ ***************************************************************************/
++
++/***************************************************************************
++ Define Difinetion
++ ***************************************************************************/
++#define SUCCESS 0 /* SUCCESS */
++#define ERROR -1 /* ERROR */
++#define CORRECT 1 /* CORRECTABLE */
++
++/***************************************************************************/
++#define NO_ERROR 0x0000 /* NO ERROR */
++#define ERR_WriteFault 0x0003 /* Peripheral Device Write Fault */
++#define ERR_HwError 0x0004 /* Hardware Error */
++#define ERR_DataStatus 0x0010 /* DataStatus Error */
++#define ERR_EccReadErr 0x0011 /* Unrecovered Read Error */
++#define ERR_CorReadErr 0x0018 /* Recovered Read Data with ECC */
++#define ERR_OutOfLBA 0x0021 /* Illegal Logical Block Address */
++#define ERR_WrtProtect 0x0027 /* Write Protected */
++#define ERR_ChangedMedia 0x0028 /* Medium Changed */
++#define ERR_UnknownMedia 0x0030 /* Incompatible Medium Installed */
++#define ERR_IllegalFmt 0x0031 /* Medium Format Corrupted */
++#define ERR_NoSmartMedia 0x003A /* Medium Not Present */
++
++/***************************************************************************
++ Common Controll Header
++ Rev 1.30('98-06-30) ***** BETA RELEASE *****
++ Copyright (c) 1997-98, Toshiba Corporation. All rights reserved.
++ ***************************************************************************/
++
++/***************************************************************************
++ SmartMedia Controller Definition
++ ***************************************************************************/
++/* I/O Mode Address */
++#define DATA(p) (p->address+0x00) /* R/W Data Reg */
++#define STATUS(p) (p->address+0x02) /* R/- Status Reg */
++#define MODE(p) (p->address+0x02) /* -/W Mode Reg */
++
++/* Controller Status Reg (Read Only) */
++#define STS_BUSY 0x80
++#define STS_VCC 0x10
++#define STS_SCHG 0x08
++#define STS_WP 0x01
++#define STS_CENB 0x04
++
++#ifdef CONFIG_SH_TITAN
++/* Controller Mode Reg (Write Only) */
++/* keep PCI clock running on bit 3 */
++/* CE# on bit 2, CLE on bit 1 and ALE on bit 0 */
++#define STANDBY (0x00 | 0x00 | 0x08)
++#define WR_DATA (0x00 | 0x04 | 0x08)
++#define WR_CMD (0x02 | 0x04 | 0x08)
++#define WR_ADR (0x01 | 0x04 | 0x08)
++#else
++/* Controller Mode Reg (Write Only) */
++#define STANDBY 0x00
++#define WR_DATA 0x10
++#define WR_CMD 0x11
++#define WR_ADR 0x12
++#define PW_OFF 0x80
++#define PW_ON 0x88
++#endif
++
++/***************************************************************************/
++#define _HwSetData(p) ctrl_outb(WR_DATA,MODE(p))
++#define _HwSetCmd(p) ctrl_outb(WR_CMD,MODE(p))
++#define _HwSetAddr(p) ctrl_outb(WR_ADR,MODE(p))
++#define _HwSetStandby(p) ctrl_outb(STANDBY,MODE(p))
++
++#define _HwInData(p) ctrl_inb(DATA(p))
++#define _HwOutData(p,a) ctrl_outb((a),DATA(p))
++
++#ifdef CONFIG_SH_TITAN
++#define _HwVccOn(p)
++#define _HwVccOff(p)
++#else
++#define _HwVccOn(p) ctrl_outb(PW_ON,MODE(p))
++#define _HwVccOff(p) ctrl_outb(PW_OFF,MODE(p))
++#endif
++
++#ifdef CONFIG_SH_TITAN
++#define _HwChkCardIn(p) (1)
++#define _HwChkStatus(p) (0)
++#define _HwChkWP(p) (0)
++#define _HwChkPower(p) (1)
++#define _HwChkBusy(p) (ctrl_inb(STATUS(p))&STS_BUSY)
++
++#else
++
++#define _HwChkCardIn(p) (ctrl_inb(STATUS(p))&STS_CENB)
++#define _HwChkStatus(p) (ctrl_inb(STATUS(p))&(STS_SCHG))
++#define _HwChkWP(p) (ctrl_inb(STATUS(p))&(STS_WP))
++#define _HwChkPower(p) (ctrl_inb(STATUS(p))&(STS_VCC))
++#define _HwChkBusy(p) (ctrl_inb(STATUS(p))&STS_BUSY)
++
++#endif
++
++#define _HwRdStatus(p) (ctrl_inb(STATUS(p)))
++/***************************************************************************/
++#ifdef CONFIG_SH_NIMBLE_MINI
++#define CPLD_BASE_ADDRESS 0xB4030000L
++#define SMART_MEDIA_ONE_OFFSET 0x08 // The "built-in" SmartMedia
++#define SMART_MEDIA_TWO_OFFSET 0x00 // The "removable" SmartMedia
++#elif CONFIG_SH_TITAN
++#define CPLD_BASE_ADDRESS 0xA4000000L
++#define SMART_MEDIA_ONE_OFFSET 0x00
++#else
++#define CPLD_BASE_ADDRESS 0xB8030000L
++#define SMART_MEDIA_ONE_OFFSET 0x00 // The "built-in" SmartMedia
++#endif
++
++/***************************************************************************
++ Program & Macro for SmartMedia Controller
++ Rev 0.30('98-06-30) ***** BETA RELEASE *****
++ Copyright (c) 1997-98, Toshiba Corporation. All rights reserved.
++ ***************************************************************************/
++/***************************************************************************
++ Define Definition
++ ***************************************************************************/
++#define K_BYTE 1024 /* Kilo Byte */
++#define SSFDC_SECTSIZE 512 /* Sector buffer size */
++#define SSFDC_BLKSIZE (K_BYTE * 4)
++#define REDTSIZE 16 /* Redundant buffer size */
++
++/***************************************************************************/
++#define DUMMY_DATA 0xFF /* No Assign Sector Read Data */
++
++/***************************************************************************
++ Max Zone/Block/Sectors Data Definition
++ ***************************************************************************/
++#define MAX_ZONENUM 0x08 /* Max Zone Numbers in a SmartMedia */
++#define MAX_BLOCKNUM 0x0400 /* Max Block Numbers in a Zone */
++#define MAX_SECTNUM 0x20 /* Max Sector Numbers in a Block */
++#define MAX_LOGBLOCK 1000 /* Max Logical Block Numbers in a Zone */
++
++/***************************************************************************
++ Logical to Physical Block Table Data Definition
++ ***************************************************************************/
++#define NO_ASSIGN 0xFFFF /* No Assign Logical Block Address */
++
++/***************************************************************************
++ 'SectCopyMode' Data
++ ***************************************************************************/
++#define COMPLETED 0 /* Sector Copy Completed */
++#define REQ_ERASE 1 /* Request Read Block Erase */
++#define REQ_FAIL 2 /* Request Read Block Failed */
++
++/***************************************************************************
++ Retry Counter Definition
++ ***************************************************************************/
++#define RDERR_REASSIGN 1 /* Reassign with Read Error */
++#define L2P_ERR_ERASE 1 /* BlockErase for Contradicted L2P Table */
++
++/***************************************************************************
++ SmartMedia Command & Status Definition
++ ***************************************************************************/
++/* SmartMedia Command */
++#define SSFDC_WRDATA 0x80
++#define SSFDC_READ 0x00
++#define SSFDC_READ_REDT 0x50
++#define SSFDC_READ1 0x00
++#define SSFDC_READ2 0x01
++#define SSFDC_READ3 0x50
++#define SSFDC_RST_CHIP 0xFF
++#define SSFDC_WRITE 0x10
++#define SSFDC_DUMMY_WRITE 0x11
++#define SSFDC_MULTI_WRITE 0x15
++#define SSFDC_ERASE1 0x60
++#define SSFDC_ERASE2 0xD0
++#define SSFDC_RDSTATUS 0x70
++#define SSFDC_READ_ID 0x90
++
++/* SmartMedia Status */
++#define WR_FAIL 0x01 /* 0:Pass, 1:Fail */
++#define SUSPENDED 0x20 /* 0:Not Suspended, 1:Suspended */
++#define READY 0x40 /* 0:Busy, 1:Ready */
++#define WR_PRTCT 0x80 /* 0:Protect, 1:Not Protect */
++
++#define USEC 1
++#define MSEC 1000 * USEC
++#define JIFFY_TICK_MS (MSEC / HZ)
++
++// #define BUSY_PROG 20 * MSEC /* 200-1000us ----- Program Time */
++#define BUSY_PROG 1000 * USEC /* 200-1000us ----- Program Time */
++#define BUSY_DUMMY_WRITE 10 * USEC /* 2-10us dummy write */
++#define BUSY_MULTI_WRITE 1000 * USEC /* 200 - 1000 usec */
++#define BUSY_ERASE 10 * MSEC /* 2-10ms ----- Block Erase Time */
++#define BUSY_READ 100 * USEC /* tR : 100us ----- Data transfer Time */
++#define BUSY_RESET 10 * USEC /* tRST : 10us ----- Device Resetting Time */
++#define BUSY_ADDR_SET 25 * USEC
++
++#define TIME_PON 30 /* 300ms ------ Power On Wait Time */
++#define TIME_CDCHK 2 /* 20ms ------ Card Check Interval Timer */
++#define TIME_WPCHK 1 /* 5ms ------ WP Check Interval Timer */
++
++/* Power On Timeout */
++#define POWER_ON_TIMEOUT (HZ*2)
++
++/* Default retry limit for Read/Write */
++#define RD_RETRY_LIMIT 3
++#define WR_RETRY_LIMIT 4
++#define BLOCK_READ_RETRY_LIMIT 2
++#define BLOCK_WRITE_RETRY_LIMIT 3
++#define REASSIGN_RETRY_LIMIT 4
++
++/***************************************************************************
++ Redundant Data
++ ***************************************************************************/
++#define REDT_DATA 0x04
++#define REDT_BLOCK 0x05
++
++#define REDT_ADDR1H 0x06
++#define REDT_ADDR1L 0x07
++#define REDT_ADDR2H 0x0B
++#define REDT_ADDR2L 0x0C
++
++#define REDT_ECC10 0x0D
++#define REDT_ECC11 0x0E
++#define REDT_ECC12 0x0F
++
++#define REDT_ECC20 0x08
++#define REDT_ECC21 0x09
++#define REDT_ECC22 0x0A
++
++/***************************************************************************
++ SmartMedia Model & Attribute
++ ***************************************************************************/
++/* SmartMedia Attribute */
++#define NOWP 0x00 /* 0... .... No Write Protect */
++#define WP 0x80 /* 1... .... Write Protected */
++#define MASK 0x00 /* .00. .... NAND MASK ROM Model */
++#define FLASH 0x20 /* .01. .... NAND Flash ROM Model */
++#define AD3CYC 0x00 /* ...0 .... Address 3-cycle */
++#define AD4CYC 0x10 /* ...1 .... Address 4-cycle */
++#define BS16 0x00 /* .... 00.. 16page/block */
++#define BS32 0x04 /* .... 01.. 32page/block */
++#define PS256 0x00 /* .... ..00 256byte/page */
++#define PS512 0x01 /* .... ..01 512byte/page */
++
++#define MWP 0x80 /* WriteProtect mask */
++#define MFLASH 0x60 /* Flash Rom mask */
++#define MADC 0x10 /* Address Cycle */
++#define MBS 0x0C /* BlockSize mask */
++#define MPS 0x03 /* PageSize mask */
++
++/* SmartMedia Model */
++#define NOSSFDC 0x00 /* NO SmartMedia */
++#define SSFDC1MB 0x01 /* 1MB SmartMedia */
++#define SSFDC2MB 0x02 /* 2MB SmartMedia */
++#define SSFDC4MB 0x03 /* 4MB SmartMedia */
++#define SSFDC8MB 0x04 /* 8MB SmartMedia */
++#define SSFDC16MB 0x05 /* 16MB SmartMedia */
++#define SSFDC32MB 0x06 /* 32MB SmartMedia */
++#define SSFDC64MB 0x07 /* 64MB SmartMedia */
++#define SSFDC128MB 0x08 /*128MB SmartMedia */
++
++#define EVEN 0 /* Even Page for 256byte/page */
++#define ODD 1 /* Odd Page for 256byte/page */
++
++/***************************************************************************
++ Struct Definition
++ ***************************************************************************/
++/* Linux kernel additions */
++
++/* device buffer xfer status */
++typedef enum { xfer_idle, xfer_busy} xfer_states;
++
++/* Smartmedia device structure */
++typedef struct {
++ unsigned long address;
++ int sm_minor;
++ int sm_flags;
++ int busy;
++ int waiting;
++
++ /* queue of io requests for the device */
++ spinlock_t req_queue_lock;
++ request_queue_t *req_queue;
++
++ /* our thread related parameters */
++ struct completion thread_dead;
++ int exiting;
++ wait_queue_head_t thread_wq;
++
++ /* accounting variables for each buffer io operation
++ each request may have a chain of buffers, each of
++ which may require I/O of multiple sectors */
++ unsigned int ReqSectorSize;
++ unsigned int BufIndex;
++ unsigned int SectorWriteIndex;
++
++ /* CHS parameters */
++ unsigned int HostCyl;
++ unsigned char HostHead;
++ unsigned char HostSect;
++
++ /* State Information */
++ xfer_states XferState;
++ unsigned int UseCount;
++ unsigned int RetryCount;
++ unsigned int ErrCode;
++ unsigned int MediaChange;
++ unsigned int CardPresent;
++ unsigned int SectCopyMode;
++
++ /* Working Databuf Area */
++ unsigned char SectBuf[SSFDC_SECTSIZE];
++ unsigned char WorkBuf[SSFDC_SECTSIZE];
++ unsigned char Redundant[REDTSIZE];
++ unsigned char WorkRedund[REDTSIZE];
++ unsigned int DataBuf_Valid;
++ unsigned int Log2Phy[MAX_ZONENUM][MAX_LOGBLOCK];
++ unsigned char Assign[MAX_ZONENUM][MAX_BLOCKNUM/8];
++ unsigned int AssignStart[MAX_ZONENUM];
++ unsigned int ReadBlock;
++ unsigned int WriteBlock;
++
++ /* Card attributes */
++ unsigned char Model;
++ unsigned char Attribute;
++ unsigned char MaxZones;
++ unsigned char MaxSectors;
++ unsigned int MaxBlocks;
++ unsigned int MaxLogBlocks;
++
++ /* Address of current access (Media) */
++ unsigned char Zone; /* Zone Number */
++ unsigned char Sector; /* Sector(512byte) Number on Block */
++ unsigned int PhyBlock; /* Physical Block Number on Zone */
++ unsigned int LogBlock; /* Logical Block Number of Zone */
++
++ /* device statistics */
++ unsigned int Sector_reads;
++ unsigned int Sector_writes;
++ unsigned int Sect_rd_errs_ttl;
++ unsigned int Sect_wr_errs_ttl;
++ unsigned int Bad_blks_rd;
++ unsigned int Bad_blks_wr;
++ unsigned int Bad_blks_erase;
++} ssfdc_dev;
++
++
++/****************************************************************************/
++/* Handy defines */
++/****************************************************************************/
++#define WRITE_PROTECTED(p) (p->Attribute & WP)
++
++/* End of Linux kernel additions */
++#endif /* #ifndef _SSFDC_H */
diff --git a/packages/linux/linux-titan-sh4_2.6.16.bb b/packages/linux/linux-titan-sh4_2.6.16.bb
new file mode 100644
index 0000000000..2c4316aea0
--- /dev/null
+++ b/packages/linux/linux-titan-sh4_2.6.16.bb
@@ -0,0 +1,49 @@
+SECTION = "kernel"
+DESCRIPTION = "Linux kernel for SH4 based TITAN router appliance"
+LICENSE = "GPL"
+MAINTAINER = "Jamie Lenehan <lenehan@twibble.org>
+PR = "r0"
+
+# The "date=20060328" should be changed to "tag=linux-2_6_16" - but the
+# tag won't exit till 2.6.17 is released
+SRC_URI = "ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-${PV}.tar.bz2 \
+cvs://anonymous@linuxsh.cvs.sourceforge.net/cvsroot/linuxsh;module=linux;data=20060331 \
+ file://titan-flash.patch;patch=1 \
+ file://titan-config"
+S = "${WORKDIR}/linux-${PV}"
+
+COMPATIBLE_HOST = 'sh4.*-linux'
+
+inherit kernel
+
+ARCH = "sh"
+KERNEL_IMAGETYPE = "vmlinux"
+KERNEL_OUTPUT = "${KERNEL_IMAGETYPE}"
+
+#
+# The linux-sh cvs tree is a "drop in source tree" and needs to be copied
+# over the top of the normal linux source since it only includes modified
+# files.
+#
+do_unpack_extra(){
+ cp -pPR ${WORKDIR}/linux/* ${S}
+}
+addtask unpack_extra after do_unpack before do_patch
+
+#
+# Use an updated defconfig which includes the flash driver
+# The flash driver quality doesn't allow it to be a part of the main kernel
+#
+do_configure_prepend() {
+ install -m 0644 ${WORKDIR}/titan-config ${S}/arch/sh/configs/titan_defconfig
+ yes '' | oe_runmake titan_defconfig
+}
+
+#
+# Should I make the nfs boot image?
+#
+#do_deploy_titan() {
+# To NFS boot you need to objcopy the image...
+# ${HOST_PREFIX}objcopy -O binary -R .note -R .comment -S arch/sh/boot/compressed/vmlinux ${DEPLOY_DIR}/linux.bin
+#}
+#addtask deploy before do_build after do_compile