linux/linux-titan-sh4-2.6.16: Add a 2.6.16 kernel for the sh4 based "titan"
authorJamie Lenehan <lenehan@twibble.org>
Wed, 28 Jun 2006 01:40:03 +0000 (01:40 +0000)
committerOpenEmbedded Project <openembedded-devel@lists.openembedded.org>
Wed, 28 Jun 2006 01:40:03 +0000 (01:40 +0000)
board. This is the only sh4 compatible kernel in OE.

packages/linux/linux-titan-sh4-2.6.16/.mtn2git_empty [new file with mode: 0644]
packages/linux/linux-titan-sh4-2.6.16/titan-config [new file with mode: 0644]
packages/linux/linux-titan-sh4-2.6.16/titan-flash.patch [new file with mode: 0644]
packages/linux/linux-titan-sh4_2.6.16.bb [new file with mode: 0644]

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 (file)
index 0000000..e69de29
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 (file)
index 0000000..4b74c91
--- /dev/null
@@ -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 (file)
index 0000000..5a68c4e
--- /dev/null
@@ -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 (file)
index 0000000..2c4316a
--- /dev/null
@@ -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