diff options
40 files changed, 7786 insertions, 2928 deletions
@@ -1217,9 +1217,10 @@ S: Chapel Hill, North Carolina 27514-4818 S: USA N: Dave Jones +E: davej@suse.de E: dave@powertweak.com E: djones2@glam.ac.uk -W: http://linux.powertweak.com +W: http://powertweak.sourceforge.net D: Moved PCI bridge tuning to userspace (Powertweak). D: Centaur/IDT Winchip/Winchip 2 tweaks. D: AFFS fixes for 2.3.x diff --git a/Documentation/Changes b/Documentation/Changes index 9479dc463..f856fe16b 100644 --- a/Documentation/Changes +++ b/Documentation/Changes @@ -43,7 +43,7 @@ with pcmcia-cs. o Gnu C 2.7.2.3 # gcc --version o binutils 2.9.1.0.22 # ld -v o util-linux 2.10g # chsh -v -o modutils 2.3.10 # insmod -V +o modutils 2.3.13 # insmod -V o e2fsprogs 1.18 # /sbin/tune2fs --version o pcmcia-cs 3.1.13 # cardmgr -V o PPP 2.4.0b1 # pppd --version @@ -266,8 +266,8 @@ o ftp://ftp.kernel.org/pub/linux/utils/kernel/ksymoops/v2.3 Modutils -------- -o ftp://ftp.kernel.org/pub/linux/utils/kernel/modutils/v2.3/modutils-2.3.9.tar.gz - <ftp://ftp.kernel.org/pub/linux/utils/kernel/modutils/v2.3/modutils-2.3.9.tar.gz> +o ftp://ftp.kernel.org/pub/linux/utils/kernel/modutils/v2.3/modutils-2.3.13.tar.gz + <ftp://ftp.kernel.org/pub/linux/utils/kernel/modutils/v2.3/modutils-2.3.13.tar.gz> E2fsprogs --------- diff --git a/Documentation/Configure.help b/Documentation/Configure.help index b64444b26..b94126f2c 100644 --- a/Documentation/Configure.help +++ b/Documentation/Configure.help @@ -4649,9 +4649,11 @@ CONFIG_PACKET_MMAP Kernel/User network link driver CONFIG_NETLINK This driver allows for two-way communication between the kernel and - user processes; the user processes communicate with the kernel by - reading from and writing to character special files in the /dev - directory having major mode 36. + user processes. It does so by creating a new socket family, PF_NETLINK. + Over this socket, the kernel can send and receive datagrams carrying + information. It is documented on many systems in netlink(7), a HOWTO is + provided as well, for example on + http://snafu.freedom.org/linux2.2/docs/netlink-HOWTO.html So far, the kernel uses this feature to publish some network related information if you say Y to "Routing messages", below. You also need @@ -4665,16 +4667,19 @@ CONFIG_NETLINK Routing messages CONFIG_RTNETLINK - If you say Y here and create a character special file /dev/route - with major number 36 and minor number 0 using mknod ("man mknod"), - you (or some user space utility) can read some network related - routing information from that file. Everything you write to that - file will be discarded. + If you say Y here, userspace programs can receive some network + related routing information over the netlink. 'rtmon', supplied + with the iproute2 package (ftp://ftp.inr.ac.ru), can read and + interpret this data. Information sent to the kernel over this link + is ignored. Netlink device emulation CONFIG_NETLINK_DEV + This option will be removed soon. Any programs that want to use + character special nodes like /dev/tap0 or /dev/route (all with major + number 36) need this option, and need to be rewritten soon to use + the real netlink socket. This is a backward compatibility option, choose Y for now. - This option will be removed soon. Asynchronous Transfer Mode (ATM) CONFIG_ATM diff --git a/Documentation/README.DAC960 b/Documentation/README.DAC960 index 2a80042dc..8166455b0 100644 --- a/Documentation/README.DAC960 +++ b/Documentation/README.DAC960 @@ -1,47 +1,52 @@ - Mylex DAC960/DAC1100 PCI RAID Controller Driver for Linux + Linux Driver for Mylex DAC960/AcceleRAID/eXtremeRAID PCI RAID Controllers - Version 2.2.4 for Linux 2.2.11 - Version 2.0.4 for Linux 2.0.37 + Version 2.2.7 for Linux 2.2.16 + Version 2.4.7 for Linux 2.4.0 PRODUCTION RELEASE - 23 August 1999 + 1 August 2000 Leonard N. Zubkoff Dandelion Digital lnz@dandelion.com - Copyright 1998-1999 by Leonard N. Zubkoff <lnz@dandelion.com> + Copyright 1998-2000 by Leonard N. Zubkoff <lnz@dandelion.com> INTRODUCTION Mylex, Inc. designs and manufactures a variety of high performance PCI RAID controllers. Mylex Corporation is located at 34551 Ardenwood Blvd., Fremont, -California 94555, USA and can be reached at 510/796-6100 or on the World Wide -Web at http://www.mylex.com. Mylex RAID Technical Support can be reached by -electronic mail at support@mylex.com (for eXtremeRAID 1100 and older DAC960 -models) or techsup@mylex.com (for AcceleRAID models), by voice at 510/608-2400, -or by FAX at 510/745-7715. Contact information for offices in Europe and Japan -is available on the Web site. +California 94555, USA and can be reached at 510.796.6100 or on the World Wide +Web at http://www.mylex.com. Mylex Technical Support can be reached by +electronic mail at support@mylex.com, by voice at 510.608.2400, or by FAX at +510.745.7715. Contact information for offices in Europe and Japan is available +on their Web site. The latest information on Linux support for DAC960 PCI RAID Controllers, as well as the most recent release of this driver, will always be available from my Linux Home Page at URL "http://www.dandelion.com/Linux/". The Linux DAC960 -driver supports all current DAC960 PCI family controllers including the -AcceleRAID models, as well as the eXtremeRAID 1100; see below for a complete -list. For simplicity, in most places this documentation refers to DAC960 -generically rather than explicitly listing all the models. - -Bug reports should be sent via electronic mail to "lnz@dandelion.com". Please -include with the bug report the complete configuration messages reported by the -driver at startup, along with any subsequent system messages relevant to the -controller's operation, and a detailed description of your system's hardware -configuration. - -Please consult the DAC960 RAID controller documentation for detailed -information regarding installation and configuration of the controllers. This -document primarily provides information specific to the Linux DAC960 support. +driver supports all current Mylex PCI RAID controllers including the new +eXtremeRAID 2000/3000 and AcceleRAID 352/170 models which have an entirely new +firmware interface from the older eXtremeRAID 1100, AcceleRAID 150/200/250, and +DAC960PJ/PG/PU/PD/PL. See below for a complete controller list as well as +minimum firmware version requirements. For simplicity, in most places this +documentation refers to DAC960 generically rather than explicitly listing all +the supported models. + +Driver bug reports should be sent via electronic mail to "lnz@dandelion.com". +Please include with the bug report the complete configuration messages reported +by the driver at startup, along with any subsequent system messages relevant to +the controller's operation, and a detailed description of your system's +hardware configuration. Driver bugs are actually quite rare; if you encounter +problems with disks being marked offline, for example, please contact Mylex +Technical Support as the problem is related to the hardware configuration +rather than the Linux driver. + +Please consult the RAID controller documentation for detailed information +regarding installation and configuration of the controllers. This document +primarily provides information specific to the Linux support. DRIVER FEATURES @@ -60,16 +65,18 @@ of the controller and adding new disk drives, most everything can be handled from Linux while the system is operational. The DAC960 driver is architected to support up to 8 controllers per system. -Each DAC960 controller can support up to 15 disk drives per channel, for a -maximum of 45 drives on a three channel controller. The drives installed on a -controller are divided into one or more "Drive Groups", and then each Drive -Group is subdivided further into 1 to 32 "Logical Drives". Each Logical Drive -has a specific RAID Level and caching policy associated with it, and it appears -to Linux as a single block device. Logical Drives are further subdivided into -up to 7 partitions through the normal Linux and PC disk partitioning schemes. -Logical Drives are also known as "System Drives", and Drive Groups are also -called "Packs". Both terms are in use in the Mylex documentation; I have -chosen to standardize on the more generic "Logical Drive" and "Drive Group". +Each DAC960 parallel SCSI controller can support up to 15 disk drives per +channel, for a maximum of 60 drives on a four channel controller; the fibre +channel eXtremeRAID 3000 controller supports up to 125 disk drives per loop for +a total of 250 drives. The drives installed on a controller are divided into +one or more "Drive Groups", and then each Drive Group is subdivided further +into 1 to 32 "Logical Drives". Each Logical Drive has a specific RAID Level +and caching policy associated with it, and it appears to Linux as a single +block device. Logical Drives are further subdivided into up to 7 partitions +through the normal Linux and PC disk partitioning schemes. Logical Drives are +also known as "System Drives", and Drive Groups are also called "Packs". Both +terms are in use in the Mylex documentation; I have chosen to standardize on +the more generic "Logical Drive" and "Drive Group". DAC960 RAID disk devices are named in the style of the Device File System (DEVFS). The device corresponding to Logical Drive D on Controller C is @@ -82,17 +89,41 @@ controller. The 8 bits of minor number are divided into 5 bits for the Logical Drive and 3 bits for the partition. - SUPPORTED DAC960/DAC1100 PCI RAID CONTROLLERS + SUPPORTED DAC960/AcceleRAID/eXtremeRAID PCI RAID CONTROLLERS -The following list comprises the supported DAC960 and DAC1100 PCI RAID -Controllers as of the date of this document. It is recommended that anyone -purchasing a Mylex PCI RAID Controller not in the following table contact the -author beforehand to verify that it is or will be supported. +The following list comprises the supported DAC960, AcceleRAID, and eXtremeRAID +PCI RAID Controllers as of the date of this document. It is recommended that +anyone purchasing a Mylex PCI RAID Controller not in the following table +contact the author beforehand to verify that it is or will be supported. + +eXtremeRAID 3000 + 1 Wide Ultra-2/LVD SCSI channel + 2 External Fibre FC-AL channels + 233MHz StrongARM SA 110 Processor + 64 Bit 33MHz PCI (backward compatible with 32 Bit PCI slots) + 32MB/64MB ECC SDRAM Memory + +eXtremeRAID 2000 + 4 Wide Ultra-160 LVD SCSI channels + 233MHz StrongARM SA 110 Processor + 64 Bit 33MHz PCI (backward compatible with 32 Bit PCI slots) + 32MB/64MB ECC SDRAM Memory + +AcceleRAID 352 + 2 Wide Ultra-160 LVD SCSI channels + 100MHz Intel i960RN RISC Processor + 64 Bit 33MHz PCI (backward compatible with 32 Bit PCI slots) + 32MB/64MB ECC SDRAM Memory + +AcceleRAID 170 + 1 Wide Ultra-160 LVD SCSI channel + 100MHz Intel i960RM RISC Processor + 16MB/32MB/64MB ECC SDRAM Memory eXtremeRAID 1100 (DAC1164P) 3 Wide Ultra-2/LVD SCSI channels 233MHz StrongARM SA 110 Processor - 64 Bit PCI (backward compatible with 32 Bit PCI slots) + 64 Bit 33MHz PCI (backward compatible with 32 Bit PCI slots) 16MB/32MB/64MB Parity SDRAM Memory with Battery Backup AcceleRAID 250 (DAC960PTL1) @@ -133,6 +164,9 @@ DAC960PL 1/2/3 Wide Fast SCSI-2 Channels Intel i960 RISC Processor 2MB/4MB/8MB/16MB/32MB DRAM Memory +For the eXtremeRAID 2000/3000 and AcceleRAID 352/170, firmware version 6.00-01 +or above is required. + For the eXtremeRAID 1100, firmware version 5.06-0-52 or above is required. For the AcceleRAID 250, 200, and 150, firmware version 4.06-0-57 or above is @@ -163,13 +197,13 @@ ftp://ftp.mylex.com/pub/dac960/diskcomp.html. DRIVER INSTALLATION -This distribution was prepared for Linux kernel version 2.2.11 or 2.0.37. +This distribution was prepared for Linux kernel version 2.2.16 or 2.4.0. To install the DAC960 RAID driver, you may use the following commands, replacing "/usr/src" with wherever you keep your Linux kernel source tree: cd /usr/src - tar -xvzf DAC960-2.2.4.tar.gz (or DAC960-2.0.4.tar.gz) + tar -xvzf DAC960-2.2.7.tar.gz (or DAC960-2.4.7.tar.gz) mv README.DAC960 linux/Documentation mv DAC960.[ch] linux/drivers/block patch -p0 < DAC960.patch @@ -201,13 +235,13 @@ system, the controller must first be configured to provide one or more logical drives using the BIOS Configuration Utility or DACCF. Please note that since there are only at most 6 usable partitions on each logical drive, systems requiring more partitions should subdivide a drive group into multiple logical -drives, each of which can have up to 6 partitions. Also, note that with large -disk arrays it is advisable to enable the 8GB BIOS Geometry (255/63) rather -than accepting the default 2GB BIOS Geometry (128/32); failing to so do will -cause the logical drive geometry to have more than 65535 cylinders which will -make it impossible for FDISK to be used properly. The 8GB BIOS Geometry can be -enabled by configuring the DAC960 BIOS, which is accessible via Alt-M during -the BIOS initialization sequence. +drives, each of which can have up to 6 usable partitions. Also, note that with +large disk arrays it is advisable to enable the 8GB BIOS Geometry (255/63) +rather than accepting the default 2GB BIOS Geometry (128/32); failing to so do +will cause the logical drive geometry to have more than 65535 cylinders which +will make it impossible for FDISK to be used properly. The 8GB BIOS Geometry +can be enabled by configuring the DAC960 BIOS, which is accessible via Alt-M +during the BIOS initialization sequence. For maximum performance and the most efficient E2FSCK performance, it is recommended that EXT2 file systems be built with a 4KB block size and 16 block diff --git a/Documentation/ia64/README b/Documentation/ia64/README index 54b591caa..738572a80 100644 --- a/Documentation/ia64/README +++ b/Documentation/ia64/README @@ -57,8 +57,8 @@ IA-64 SPECIFICS table and only if that fails fall back on walking the page table tree. - o Discontinuous large memory support; memory above 4GB will be - discontinuous since the 4GB-64MB is reserved for firmware and I/O + o Discontiguous large memory support; memory above 4GB will be + discontiguous since the 4GB-64MB is reserved for firmware and I/O space. o Correct mapping for PAL runtime code; PAL code needs to be diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 42f894248..d3c8bbdaa 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -20,6 +20,8 @@ restrictions referred to are that the relevant option is valid if: EIDE EIDE/ATAPI support is enabled. FB The frame buffer device is enabled. HW Appropriate hardware is enabled. + IA-32 IA-32 aka i386 architecture is enabled. + IA-64 IA-64 architecture is enabled. ISDN Appropriate ISDN support is enabled. JOY Appropriate joystick support is enabled. LP Printer support is enabled. @@ -396,7 +398,36 @@ running once the system is up. pcd. [PARIDE] - pci= [PCI] + pci=option[,option...] [PCI] various PCI subsystem options: + off [IA-32] don't probe for the PCI bus + bios [IA-32] force use of PCI BIOS, don't access + the hardware directly. Use this if your machine + has a non-standard PCI host bridge. + nobios [IA-32] disallow use of PCI BIOS, only direct + hardware access methods are allowed. Use this + if you experience crashes upon bootup and you + suspect they are caused by the BIOS. + conf1 [IA-32] Force use of PCI Configuration Mechanism 1. + conf2 [IA-32] Force use of PCI Configuration Mechanism 2. + nosort [IA-32] Don't sort PCI devices according to + order given by the PCI BIOS. This sorting is done + to get a device order compatible with older kernels. + biosirq [IA-32] Use PCI BIOS calls to get the interrupt + routing table. These calls are known to be buggy + on several machines and they hang the machine when used, + but on other computers it's the only way to get the + interrupt routing table. Try this option if the kernel + is unable to allocate IRQs or discover secondary PCI + buses on your motherboard. + rom [IA-32] Assign address space to expansion ROMs. + Use with caution as certain devices share address + decoders between ROMs and other resources. + irqmask=0xMMMM [IA-32] Set a bit mask of IRQs allowed to be assigned + automatically to PCI devices. You can make the kernel + exclude IRQs of your ISA cards this way. + lastbus=N [IA-32] Scan all buses till bus #N. Can be useful + if the kernel is unable to find your secondary buses + and you want to tell it explicitly which ones they are. pd. [PARIDE] diff --git a/Documentation/networking/ethertap.txt b/Documentation/networking/ethertap.txt index 653f043a7..4a27cd899 100644 --- a/Documentation/networking/ethertap.txt +++ b/Documentation/networking/ethertap.txt @@ -1,88 +1,262 @@ -Documentation on setup and use of EtherTap. +Ethertap programming mini-HOWTO +------------------------------- -Contact Jay Schulist <jschlst@turbolinux.com> if you -have questions or need further assistance. +The ethertap driver was written by Jay Schulist <jschlst@turbolinux.com>, +you should contact him for further information. This document was written by +bert hubert <bert.hubert@netherlabs.nl>. Updates are welcome. -Introduction -============ +What ethertap can do for you +---------------------------- -Ethertap provides packet reception and transmission for user -space programs. It can be viewed as a simple Ethernet device, -which instead of receiving packets from a network wire, it receives -them from user space. +Ethertap allows you to easily run your own network stack from userspace. +Tunnels can benefit greatly from this. You can also use it to do network +experiments. The alternative would be to use a raw socket to send data and +use libpcap to receive it. Using ethertap saves you this multiplicity and +also does ARP for you if you want. -Ethertap can be used for anything from AppleTalk to IPX to even -building bridging tunnels. It also has many other general purpose -uses. +The more technical blurb: -Ethertap also can do ARP for you, although this is not enabled by -default. +Ethertap provides packet reception and transmission for user space programs. +It can be viewed as a simple Ethernet device, which instead of receiving +packets from a network wire, it receives them from user space. -SetUp -===== +Ethertap can be used for anything from AppleTalk to IPX to even building +bridging tunnels. It also has many other general purpose uses. -First you will have to enable Ethertap in the kernel configuration. -Then you will need to create any number of ethertap device files, -/dev/tap0->/dev/tap15. This is done by the following command. +Configuring your kernel +----------------------- -mknod /dev/tap* c 36 16 ( 17 18 19 20 for tap1,2,3,4...) +Firstly, you need this in Networking Options: -** Replace * with the proper tap device number you need. ** + # + # Code maturity level options + # + CONFIG_EXPERIMENTAL=y -Now with your kernel that has ethertap enabled, you will need -to ifconfig /dev/tap* 192.168.1.1 (replace 192.168.1.1 with the -proper IP number for your situation.) +Then you need Netlink support: -If you want your Ethertap device to ARP for you would ifconfig -the interface like this: ifconfig tap* 192.168.1.1 arp + CONFIG_NETLINK=y -Remember that you need to have a corresponding /dev/tap* file -for each tap* device you need to ifconfig. +This allows the kernel to exchange data with userspace applications. There +are two ways of doing this, the new way works with netlink sockets and I +have no experience with that yet. ANK uses it in his excellent iproute2 +package, see for example rtmon.c. iproute2 can be found on +ftp://ftp.inr.ac.ru/ip-routing/iproute2* -Now Ethertap should be ready to use. +The new way is described, partly in netlink(7), available on +http://www.europe.redhat.com/documentation/man-pages/man7/netlink.7.php3 -Diagram of how Ethertap works. (Courtesy of Alan Cox) -==================================================== +There is also a Netlink-HOWTO, available on http://snafu.freedom.org/linux2.2/docs/netlink-HOWTO.html +Sadly I know of no code using ethertap with this new interface. -This is for a tunnel, but you should be able to -get the general idea. +The older way works by opening character special files with major node 36. +Enable this with: - 1.2.3.4 will be the router to the outside world - 1.2.3.5 our box - 2.0.0.1 our box (appletalk side) - 2.0.0.* a pile of macintoys + CONFIG_NETLINK_DEV=m +Please be advised that this support is going to be dropped somewhere in the +future! -[1.2.3.4]-------------1.2.3.5[Our Box]2.0.0.1---------> macs +Then finally in the Network Devices section, -The routing on our box would be + CONFIG_ETHERTAP=m - ifconfig eth0 1.2.3.5 netmask 255.255.255.0 up - route add default gw 1.2.3.4 - ifconfig tap0 2.0.0.1 netmask 255.255.255.0 up arp - (route add 2.0.0.0 netmask 255.255.255.0) +You can include it directly in the kernel if you want, of course, no need +for modules. -C code for a Simple program using an EtherTap device -==================================================== +Setting it all up +----------------- -This code is just excerpts from a real program, so some parts are missing -but the important stuff is below. +First we need to create the /dev/tap0 device node: -void main (void) + # mknod /dev/tap0 c 36 16 + # mknod /dev/tap1 c 36 17 + (etc) + +Include the relevant modules (ethertap.o, netlink_dev.o, perhaps netlink.o), +and bring up your tap0 device: + + # ifconfig tap0 10.0.0.123 up + +Now your device is up and running, you can ping it as well. This is what +confused me to no end, because nothing is connected to our ethertap as yet, +how is it that we can ping it? + +It turns out that the ethertap is just like a regular network interface - +even when it's down you can ping it. We need to route stuff to it: + + # route add -host 10.0.0.124 gw 10.0.0.123 + +Now we can read /dev/tap0 and when we ping 10.0.0.124 from our +localhost, output should appear on the screen. + + # cat /dev/tap0 + :ßVU:9````````````````````````şışET@?' + + +Getting this to work from other hosts +------------------------------------- + +For this to work, you often need proxy ARP. + + # echo 1 > /proc/sys/net/ipv4/conf/eth0/proxy_arp + +eth0 here stands for the interface that connects to 'other hosts'. + +Chances are that you are trying this on a non-routing desktop computer, so +you need to enable ip forwarding: + + # echo 1 > /proc/sys/net/ipv4/ip_forward + +You should now be able to ping 10.0.0.124 from other hosts on your +10.0.0.0/8 subnet. If you are using public ip space, it should work from +everywhere. + +ARP +--- + +If we were to take things very literally, your tcp/ip pseudo stack would +also have to implement ARP and MAC addresses. This is often a bit silly as +the ethertap device is a figment of our imagination anyway. However, should +you want to go 'all the way', you can add the 'arp' flag to ifconfig: + + # ifconfig tap0 10.0.0.123 up arp + +This may also be useful when implementing a bridge, which needs to bridge +ARP packets as well. + +The sample program below will no longer work then, because it does not +implement ARP. + +Sample program +-------------- + +A sample program is included somewhere in the bowels of the netfilter +source. I've extracted this program and list it here. It implements a very +tiny part of the IP stack and can respond to any pings it receives. It gets +confused if it receives ARP, as it tries to parse it by treating it as an IP +packet. + +/* Simple program to listen to /dev/tap0 and reply to pings. */ +#include <fcntl.h> +#include <netinet/ip.h> +#include <netinet/ip_icmp.h> +#if defined(__GLIBC__) && (__GLIBC__ == 2) +#include <netinet/tcp.h> +#include <netinet/udp.h> +#else +#include <linux/tcp.h> +#include <linux/udp.h> +#endif +#include <string.h> +#include <stdio.h> +#include <errno.h> +#include <unistd.h> + +u_int16_t csum_partial(void *buffer, unsigned int len, u_int16_t prevsum) { - int TapDevice, eth_pkt_len = 0; - unsigned char full_pkt_len[MAX_PKT_LEN]; + u_int32_t sum = 0; + u_int16_t *ptr = buffer; + + while (len > 1) { + sum += *ptr++; + len -= 2; + } + if (len) { + union { + u_int8_t byte; + u_int16_t wyde; + } odd; + odd.wyde = 0; + odd.byte = *((u_int8_t *)ptr); + sum += odd.wyde; + } + sum = (sum >> 16) + (sum & 0xFFFF); + sum += prevsum; + return (sum + (sum >> 16)); +} + +int main() +{ + int fd, len; + union { + struct { + char etherhdr[16]; + struct iphdr ip; + } fmt; + unsigned char raw[65536]; + } u; + + fd = open("/dev/tap0", O_RDWR); + if (fd < 0) { + perror("Opening `/dev/tap0'"); + return 1; + } + + /* u.fmt.ip.ihl in host order! Film at 11. */ + while ((len = read(fd, &u, sizeof(u))) > 0) { + u_int32_t tmp; + struct icmphdr *icmp + = (void *)((u_int32_t *)&u.fmt.ip + u.fmt.ip.ihl ); + struct tcphdr *tcp = (void *)icmp; + struct udphdr *udp = (void *)icmp; + + fprintf(stderr, "SRC = %u.%u.%u.%u DST = %u.%u.%u.%u\n", + (ntohl(u.fmt.ip.saddr) >> 24) & 0xFF, + (ntohl(u.fmt.ip.saddr) >> 16) & 0xFF, + (ntohl(u.fmt.ip.saddr) >> 8) & 0xFF, + (ntohl(u.fmt.ip.saddr) >> 0) & 0xFF, + (ntohl(u.fmt.ip.daddr) >> 24) & 0xFF, + (ntohl(u.fmt.ip.daddr) >> 16) & 0xFF, + (ntohl(u.fmt.ip.daddr) >> 8) & 0xFF, + (ntohl(u.fmt.ip.daddr) >> 0) & 0xFF); + + switch (u.fmt.ip.protocol) { + case IPPROTO_ICMP: + if (icmp->type == ICMP_ECHO) { + fprintf(stderr, "PONG! (iphdr = %u bytes)\n", + (unsigned int)((char *)icmp + - (char *)&u.fmt.ip)); - TapDevice = open("/dev/tap0", O_RDWR); - if(TapDevice < 0) - { - perror("Error opening device"); - exit(1); - } + /* Turn it around */ + tmp = u.fmt.ip.saddr; + u.fmt.ip.saddr = u.fmt.ip.daddr; + u.fmt.ip.daddr = tmp; - write(TapDevice, full_packet, eth_pkt_len); + icmp->type = ICMP_ECHOREPLY; + icmp->checksum = 0; + icmp->checksum + = ~csum_partial(icmp, + ntohs(u.fmt.ip.tot_len) + - u.fmt.ip.ihl*4, 0); - close(TapDevice); + { + unsigned int i; + for (i = 44; + i < ntohs(u.fmt.ip.tot_len); i++){ + printf("%u:0x%02X ", i, + ((unsigned char *) + &u.fmt.ip)[i]); + } + printf("\n"); + } + write(fd, &u, len); + } + break; + case IPPROTO_TCP: + fprintf(stderr, "TCP: %u -> %u\n", ntohs(tcp->source), + ntohs(tcp->dest)); + break; - return; + case IPPROTO_UDP: + fprintf(stderr, "UDP: %u -> %u\n", ntohs(udp->source), + ntohs(udp->dest)); + break; + } + } + if (len < 0) + perror("Reading from `/dev/tap0'"); + else fprintf(stderr, "Empty read from `/dev/tap0'"); + return len < 0 ? 1 : 0; } + diff --git a/Documentation/vm/numa b/Documentation/vm/numa index b28fb352b..21a3442b7 100644 --- a/Documentation/vm/numa +++ b/Documentation/vm/numa @@ -14,7 +14,7 @@ across nodes, and trying to house all the data structures that key components of the kernel need on memory on that node. Currently, all the numa support is to provide efficient handling -of widely discontinuous physical memory, so architectures which +of widely discontiguous physical memory, so architectures which are not NUMA but can have huge holes in the physical address space can use the same code. All this code is bracketed by CONFIG_DISCONTIGMEM. @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 0 -EXTRAVERSION = -test6-pre2 +EXTRAVERSION = -test6-pre3 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) @@ -35,6 +35,7 @@ OBJCOPY = $(CROSS_COMPILE)objcopy OBJDUMP = $(CROSS_COMPILE)objdump MAKEFILES = $(TOPDIR)/.config GENKSYMS = /sbin/genksyms +DEPMOD = /sbin/depmod MODFLAGS = -DMODULE CFLAGS_KERNEL = PERL = perl @@ -72,11 +73,14 @@ endif #export INSTALL_PATH=/boot # -# INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory +# INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory # relocations required by build roots. This is not defined in the # makefile but the arguement can be passed to make if needed. # +MODLIB := $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE) +export MODLIB + # # standard CFLAGS # @@ -282,7 +286,7 @@ TAGS: dummy find include -type d \( -name "asm-*" -o -name config \) -prune -o -name '*.h' -print | xargs etags -a find $(SUBDIRS) init -name '*.c' | xargs etags -a -# Exuberant ctags works better with -I +# Exuberant ctags works better with -I tags: dummy CTAGSF=`ctags --version | grep -i exuberant >/dev/null && echo "-I __initdata,__initlocaldata,__exitdata,EXPORT_SYMBOL,EXPORT_SYMBOL_NOVERS"`; \ ctags $$CTAGSF `find include/asm-$(ARCH) -name '*.h'` && \ @@ -294,64 +298,49 @@ ifdef CONFIG_MODVERSIONS MODFLAGS += -DMODVERSIONS -include $(HPATH)/linux/modversions.h endif +.PHONY: modules modules: $(patsubst %, _mod_%, $(SUBDIRS)) -modules/MARKER: - mkdir -p modules - touch modules/MARKER - -$(patsubst %, _mod_%, $(SUBDIRS)) : include/linux/version.h include/config/MARKER modules/MARKER +.PHONY: $(patsubst %, _mod_%, $(SUBDIRS)) +$(patsubst %, _mod_%, $(SUBDIRS)) : include/linux/version.h include/config/MARKER $(MAKE) -C $(patsubst _mod_%, %, $@) CFLAGS="$(CFLAGS) $(MODFLAGS)" MAKING_MODULES=1 modules -modules_install: - @( \ - MODLIB=$(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE); \ - mkdir -p $$MODLIB; \ - rm -f $$MODLIB/build; \ - ln -s $$TOPDIR $$MODLIB/build; \ - cd modules; \ - MODULES=""; \ - inst_mod() { These="`cat $$1`"; MODULES="$$MODULES $$These"; \ - mkdir -p $$MODLIB/$$2; cp $$These $$MODLIB/$$2; \ - echo Installing modules under $$MODLIB/$$2; \ - }; \ - \ - if [ -f BLOCK_MODULES ]; then inst_mod BLOCK_MODULES block; fi; \ - if [ -f NET_MODULES ]; then inst_mod NET_MODULES net; fi; \ - if [ -f IPV4_MODULES ]; then inst_mod IPV4_MODULES ipv4; fi; \ - if [ -f IPV6_MODULES ]; then inst_mod IPV6_MODULES ipv6; fi; \ - if [ -f ATM_MODULES ]; then inst_mod ATM_MODULES atm; fi; \ - if [ -f IDE_MODULES ]; then inst_mod IDE_MODULES ide; fi; \ - if [ -f SCSI_MODULES ]; then inst_mod SCSI_MODULES scsi; fi; \ - if [ -f FS_MODULES ]; then inst_mod FS_MODULES fs; fi; \ - if [ -f NLS_MODULES ]; then inst_mod NLS_MODULES fs; fi; \ - if [ -f CDROM_MODULES ]; then inst_mod CDROM_MODULES cdrom; fi; \ - if [ -f HAM_MODULES ]; then inst_mod HAM_MODULES net; fi; \ - if [ -f SOUND_MODULES ]; then inst_mod SOUND_MODULES sound; fi; \ - if [ -f VIDEO_MODULES ]; then inst_mod VIDEO_MODULES video; fi; \ - if [ -f FC4_MODULES ]; then inst_mod FC4_MODULES fc4; fi; \ - if [ -f IRDA_MODULES ]; then inst_mod IRDA_MODULES net; fi; \ - if [ -f SK98LIN_MODULES ]; then inst_mod SK98LIN_MODULES net; fi; \ - if [ -f SKFP_MODULES ]; then inst_mod SKFP_MODULES net; fi; \ - if [ -f USB_MODULES ]; then inst_mod USB_MODULES usb; fi; \ - if [ -f USB_STORAGE_MODULES ]; then inst_mod USB_STORAGE_MODULES usb; fi; \ - if [ -f USB_SERIAL_MODULES ]; then inst_mod USB_SERIAL_MODULES usb; fi; \ - if [ -f IEEE1394_MODULES ]; then inst_mod IEEE1394_MODULES ieee1394; fi; \ - if [ -f MTD_MODULES ]; then inst_mod MTD_MODULES mtd; fi; \ - if [ -f PCMCIA_MODULES ]; then inst_mod PCMCIA_MODULES pcmcia; fi; \ - if [ -f PCMCIA_NET_MODULES ]; then inst_mod PCMCIA_NET_MODULES pcmcia; fi; \ - if [ -f PCMCIA_CHAR_MODULES ]; then inst_mod PCMCIA_CHAR_MODULES pcmcia; fi; \ - if [ -f PCMCIA_SCSI_MODULES ]; then inst_mod PCMCIA_SCSI_MODULES pcmcia; fi; \ - \ - ls -1 -U *.o | sort > $$MODLIB/.allmods; \ - if [ -f $$MODLIB/net/3c59x.o ]; then \ - mkdir -p $$MODLIB/pcmcia; \ - ln -nfs ../net/3c59x.o $$MODLIB/pcmcia/3c575_cb.o; \ - MODULES="$$MODULES 3c575_cb.o"; fi; \ - echo $$MODULES | tr ' ' '\n' | sort | comm -23 $$MODLIB/.allmods - > $$MODLIB/.misc; \ - if [ -s $$MODLIB/.misc ]; then inst_mod $$MODLIB/.misc misc; fi; \ - rm -f $$MODLIB/.misc $$MODLIB/.allmods; \ - ) +.PHONY: modules_install +modules_install: _modinst_ $(patsubst %, _modinst_%, $(SUBDIRS)) _modinst_post + +.PHONY: _modinst_ +_modinst_: + @rm -rf $(MODLIB)/kernel + @rm -f $(MODLIB)/build + @mkdir -p $(MODLIB)/kernel + @ln -s $(TOPDIR) $(MODLIB)/build + +# If System.map exists, run depmod. This deliberately does not have a +# dependency on System.map since that would run the dependency tree on +# vmlinux. This depmod is only for convenience to give the initial +# boot a modules.dep even before / is mounted read-write. However the +# boot script depmod is the master version. +ifeq "$(strip $(INSTALL_MOD_PATH))" "" +depmod_opts := +else +depmod_opts := -b $(INSTALL_MOD_PATH) -r +endif +.PHONY: _modinst_post +_modinst_post: _modinst_post_pcmcia + if [ -r System.map ]; then $(DEPMOD) -ae -F System.map $(depmod_opts) $(KERNELRELEASE); fi + +# Backwards compatibilty symlinks for people still using old versions +# of pcmcia-cs with hard coded pathnames on insmod. Remove +# _modinst_post_pcmcia for kernel 2.4.1. +.PHONY: _modinst_post_pcmcia +_modinst_post_pcmcia: + cd $(MODLIB); \ + mkdir -p pcmcia; \ + find kernel -path '*/pcmcia/*' -name '*.o' | xargs -i -r ln -sf ../{} pcmcia + +.PHONY: $(patsubst %, _modinst_%, $(SUBDIRS)) +$(patsubst %, _modinst_%, $(SUBDIRS)) : + $(MAKE) -C $(patsubst _modinst_%, %, $@) modules_install # modules disabled.... diff --git a/Rules.make b/Rules.make index c0263dedb..c2d795f24 100644 --- a/Rules.make +++ b/Rules.make @@ -32,8 +32,6 @@ unexport MX_OBJS unexport MIX_OBJS unexport SYMTAB_OBJS -unexport MOD_LIST_NAME - # # Get things started. # @@ -132,38 +130,33 @@ ifneq "$(strip $(ALL_MOBJS))" "" PDWN=$(shell $(CONFIG_SHELL) $(TOPDIR)/scripts/pathdown.sh) endif -ifdef MOD_SUB_DIRS -$(patsubst %,_modsubdir_%,$(MOD_SUB_DIRS)) : dummy +unexport MOD_DIRS +MOD_DIRS := $(MOD_SUB_DIRS) $(MOD_IN_SUB_DIRS) +ifneq "$(strip $(MOD_DIRS))" "" +.PHONY: $(patsubst %,_modsubdir_%,$(MOD_DIRS)) +$(patsubst %,_modsubdir_%,$(MOD_DIRS)) : dummy $(MAKE) -C $(patsubst _modsubdir_%,%,$@) modules -endif -ifdef MOD_IN_SUB_DIRS -$(patsubst %,_modinsubdir_%,$(MOD_IN_SUB_DIRS)) : dummy - $(MAKE) -C $(patsubst _modinsubdir_%,%,$@) modules +.PHONY: $(patsubst %,_modinst_%,$(MOD_DIRS)) +$(patsubst %,_modinst_%,$(MOD_DIRS)) : dummy + $(MAKE) -C $(patsubst _modinst_%,%,$@) modules_install endif +.PHONY: modules modules: $(ALL_MOBJS) $(MIX_OBJS) $(MI_OBJS) dummy \ - $(patsubst %,_modsubdir_%,$(MOD_SUB_DIRS)) \ - $(patsubst %,_modinsubdir_%,$(MOD_IN_SUB_DIRS)) -ifneq "$(strip $(MOD_LIST_NAME))" "" - rm -f $$TOPDIR/modules/$(MOD_LIST_NAME) -ifdef MOD_SUB_DIRS - for i in $(MOD_SUB_DIRS); do \ - echo `basename $$i`.o >> $$TOPDIR/modules/$(MOD_LIST_NAME); done -endif -ifneq "$(strip $(ALL_MOBJS))" "" - echo $(ALL_MOBJS) >> $$TOPDIR/modules/$(MOD_LIST_NAME) -endif -ifneq "$(strip $(MOD_TO_LIST))" "" - echo $(MOD_TO_LIST) >> $$TOPDIR/modules/$(MOD_LIST_NAME) -endif -endif + $(patsubst %,_modsubdir_%,$(MOD_DIRS)) + +.PHONY: _modinst__ +_modinst__: dummy ifneq "$(strip $(ALL_MOBJS))" "" - echo $(PDWN) - cd $$TOPDIR/modules; for i in $(ALL_MOBJS); do \ - ln -sf ../$(PDWN)/$$i $$i; done + mkdir -p $(MODLIB)/kernel/$(PDWN) + cp $(ALL_MOBJS) $(MODLIB)/kernel/$(PDWN) endif +.PHONY: modules_install +modules_install: _modinst__ \ + $(patsubst %,_modinst_%,$(MOD_DIRS)) + # # A rule to do nothing # diff --git a/arch/mips/defconfig b/arch/mips/defconfig index b3ac37d5e..d12fc720b 100644 --- a/arch/mips/defconfig +++ b/arch/mips/defconfig @@ -25,6 +25,7 @@ CONFIG_SGI_IP22=y CONFIG_ARC32=y CONFIG_PC_KEYB=y CONFIG_SGI=y +CONFIG_BOARD_SCACHE=y # CONFIG_ISA is not set # CONFIG_PCI is not set diff --git a/arch/mips/defconfig-ip22 b/arch/mips/defconfig-ip22 index a5167c1bb..75e1df200 100644 --- a/arch/mips/defconfig-ip22 +++ b/arch/mips/defconfig-ip22 @@ -25,6 +25,7 @@ CONFIG_SGI_IP22=y CONFIG_ARC32=y CONFIG_PC_KEYB=y CONFIG_SGI=y +CONFIG_BOARD_SCACHE=y # CONFIG_ISA is not set # CONFIG_PCI is not set diff --git a/arch/mips/defconfig-rm200 b/arch/mips/defconfig-rm200 index 5204e102f..a218630d2 100644 --- a/arch/mips/defconfig-rm200 +++ b/arch/mips/defconfig-rm200 @@ -26,6 +26,7 @@ CONFIG_ARC32=y CONFIG_PCI=y CONFIG_ISA=y CONFIG_PC_KEYB=y +CONFIG_BOARD_SCACHE=y # # Loadable module support diff --git a/arch/ppc/vmlinux.lds b/arch/ppc/vmlinux.lds index 7bfdc4efb..9ca864b72 100644 --- a/arch/ppc/vmlinux.lds +++ b/arch/ppc/vmlinux.lds @@ -41,6 +41,7 @@ SECTIONS *(.rodata) *(.rodata1) } + .kstrtab : { *(.kstrtab) } .fini : { *(.fini) } =0 .ctors : { *(.ctors) } .dtors : { *(.dtors) } @@ -64,6 +65,10 @@ SECTIONS __ex_table : { *(__ex_table) } __stop___ex_table = .; + __start___ksymtab = .; /* Kernel symbol table */ + __ksymtab : { *(__ksymtab) } + __stop___ksymtab = .; + . = ALIGN(32); .data.cacheline_aligned : { *(.data.cacheline_aligned) } diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index 41ec3e2f5..749b0d3da 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c @@ -1,8 +1,8 @@ /* - Linux Driver for Mylex DAC960 and DAC1100 PCI RAID Controllers + Linux Driver for Mylex DAC960/AcceleRAID/eXtremeRAID PCI RAID Controllers - Copyright 1998-1999 by Leonard N. Zubkoff <lnz@dandelion.com> + Copyright 1998-2000 by Leonard N. Zubkoff <lnz@dandelion.com> This program is free software; you may redistribute and/or modify it under the terms of the GNU General Public License Version 2 as published by the @@ -19,9 +19,8 @@ */ -#define DAC960_DriverVersion "2.3.5" -#define DAC960_DriverDate "23 January 2000" - +#define DAC960_DriverVersion "2.4.7" +#define DAC960_DriverDate "1 August 2000" #include <linux/version.h> @@ -38,11 +37,11 @@ #include <linux/malloc.h> #include <linux/proc_fs.h> #include <linux/reboot.h> +#include <linux/spinlock.h> #include <linux/timer.h> #include <linux/pci.h> #include <asm/io.h> #include <asm/segment.h> -#include <linux/spinlock.h> #include <asm/uaccess.h> #include "DAC960.h" @@ -56,7 +55,7 @@ static int /* - DAC960_ActiveControllerCount is the number of Active DAC960 Controllers + DAC960_ActiveControllerCount is the number of active DAC960 Controllers detected. */ @@ -74,23 +73,23 @@ static DAC960_Controller_T /* - DAC960_FileOperations is the File Operations structure for DAC960 Logical - Disk Devices. - Leonard, no offence, but _where_ did this C dialect come from? + DAC960_BlockDeviceOperations is the Block Device Operations structure for + DAC960 Logical Disk Devices. */ -static struct block_device_operations DAC960_FileOperations = { - open: DAC960_Open, - release: DAC960_Release, - ioctl: DAC960_IOCTL, -}; +static BlockDeviceOperations_T + DAC960_BlockDeviceOperations = + { open: DAC960_Open, + release: DAC960_Release, + ioctl: DAC960_IOCTL }; + /* - DAC960_ProcDirectoryEntry is the DAC960 /proc/driver/rd directory entry. + DAC960_ProcDirectoryEntry is the DAC960 /proc/rd directory entry. */ -static PROC_DirectoryEntry_T * - DAC960_ProcDirectoryEntry = NULL; +static PROC_DirectoryEntry_T + *DAC960_ProcDirectoryEntry; /* @@ -121,7 +120,7 @@ static void DAC960_AnnounceDriver(DAC960_Controller_T *Controller) */ static boolean DAC960_Failure(DAC960_Controller_T *Controller, - char *ErrorMessage) + unsigned char *ErrorMessage) { DAC960_Error("While configuring DAC960 PCI RAID Controller at\n", Controller); @@ -141,17 +140,128 @@ static boolean DAC960_Failure(DAC960_Controller_T *Controller, /* - DAC960_ClearCommand clears critical fields of Command. + DAC960_CreateAuxiliaryStructures allocates and initializes the auxiliary + data structures for Controller. It returns true on success and false on + failure. */ -static inline void DAC960_ClearCommand(DAC960_Command_T *Command) +static boolean DAC960_CreateAuxiliaryStructures(DAC960_Controller_T *Controller) { - DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; - CommandMailbox->Words[0] = 0; - CommandMailbox->Words[1] = 0; - CommandMailbox->Words[2] = 0; - CommandMailbox->Words[3] = 0; - Command->CommandStatus = 0; + int CommandAllocationLength, CommandAllocationGroupSize; + int CommandsRemaining = 0, CommandIdentifier, CommandGroupByteCount; + void *AllocationPointer = NULL; + if (Controller->FirmwareType == DAC960_V1_Controller) + { + CommandAllocationLength = offsetof(DAC960_Command_T, V1.EndMarker); + CommandAllocationGroupSize = DAC960_V1_CommandAllocationGroupSize; + } + else + { + CommandAllocationLength = offsetof(DAC960_Command_T, V2.EndMarker); + CommandAllocationGroupSize = DAC960_V2_CommandAllocationGroupSize; + } + Controller->CommandAllocationGroupSize = CommandAllocationGroupSize; + Controller->FreeCommands = NULL; + for (CommandIdentifier = 1; + CommandIdentifier <= Controller->DriverQueueDepth; + CommandIdentifier++) + { + DAC960_Command_T *Command; + if (--CommandsRemaining <= 0) + { + CommandsRemaining = + Controller->DriverQueueDepth - CommandIdentifier + 1; + if (CommandsRemaining > CommandAllocationGroupSize) + CommandsRemaining = CommandAllocationGroupSize; + CommandGroupByteCount = + CommandsRemaining * CommandAllocationLength; + AllocationPointer = kmalloc(CommandGroupByteCount, GFP_ATOMIC); + if (AllocationPointer == NULL) + return DAC960_Failure(Controller, "AUXILIARY STRUCTURE CREATION"); + memset(AllocationPointer, 0, CommandGroupByteCount); + } + Command = (DAC960_Command_T *) AllocationPointer; + AllocationPointer += CommandAllocationLength; + Command->CommandIdentifier = CommandIdentifier; + Command->Controller = Controller; + Command->Next = Controller->FreeCommands; + Controller->FreeCommands = Command; + Controller->Commands[CommandIdentifier-1] = Command; + } + return true; +} + + +/* + DAC960_DestroyAuxiliaryStructures deallocates the auxiliary data + structures for Controller. +*/ + +static void DAC960_DestroyAuxiliaryStructures(DAC960_Controller_T *Controller) +{ + int i; + Controller->FreeCommands = NULL; + for (i = 0; i < Controller->DriverQueueDepth; i++) + { + DAC960_Command_T *Command = Controller->Commands[i]; + if (Command != NULL && + (Command->CommandIdentifier + % Controller->CommandAllocationGroupSize) == 1) + kfree(Command); + Controller->Commands[i] = NULL; + } + if (Controller->CombinedStatusBuffer != NULL) + { + kfree(Controller->CombinedStatusBuffer); + Controller->CombinedStatusBuffer = NULL; + Controller->CurrentStatusBuffer = NULL; + } + if (Controller->FirmwareType == DAC960_V1_Controller) return; + for (i = 0; i < DAC960_MaxLogicalDrives; i++) + if (Controller->V2.LogicalDeviceInformation[i] != NULL) + { + kfree(Controller->V2.LogicalDeviceInformation[i]); + Controller->V2.LogicalDeviceInformation[i] = NULL; + } + for (i = 0; i < DAC960_V2_MaxPhysicalDevices; i++) + { + if (Controller->V2.PhysicalDeviceInformation[i] != NULL) + { + kfree(Controller->V2.PhysicalDeviceInformation[i]); + Controller->V2.PhysicalDeviceInformation[i] = NULL; + } + if (Controller->V2.InquiryUnitSerialNumber[i] != NULL) + { + kfree(Controller->V2.InquiryUnitSerialNumber[i]); + Controller->V2.InquiryUnitSerialNumber[i] = NULL; + } + } +} + + +/* + DAC960_V1_ClearCommand clears critical fields of Command for DAC960 V1 + Firmware Controllers. +*/ + +static inline void DAC960_V1_ClearCommand(DAC960_Command_T *Command) +{ + DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; + memset(CommandMailbox, 0, sizeof(DAC960_V1_CommandMailbox_T)); + Command->V1.CommandStatus = 0; +} + + +/* + DAC960_V2_ClearCommand clears critical fields of Command for DAC960 V2 + Firmware Controllers. +*/ + +static inline void DAC960_V2_ClearCommand(DAC960_Command_T *Command) +{ + DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; + memset(CommandMailbox, 0, sizeof(DAC960_V2_CommandMailbox_T)); + Command->V2.CommandStatus = 0; } @@ -202,66 +312,181 @@ static void DAC960_WaitForCommand(DAC960_Controller_T *Controller) /* - DAC960_QueueCommand queues Command. + DAC960_BA_QueueCommand queues Command for DAC960 BA Series Controllers. */ -static void DAC960_QueueCommand(DAC960_Command_T *Command) +static void DAC960_BA_QueueCommand(DAC960_Command_T *Command) { DAC960_Controller_T *Controller = Command->Controller; void *ControllerBaseAddress = Controller->BaseAddress; - DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; - DAC960_CommandMailbox_T *NextCommandMailbox; - CommandMailbox->Common.CommandIdentifier = Command - Controller->Commands; - switch (Controller->ControllerType) - { - case DAC960_V5_Controller: - NextCommandMailbox = Controller->NextCommandMailbox; - DAC960_V5_WriteCommandMailbox(NextCommandMailbox, CommandMailbox); - if (Controller->PreviousCommandMailbox1->Words[0] == 0 || - Controller->PreviousCommandMailbox2->Words[0] == 0) - { - if (Controller->DualModeMemoryMailboxInterface) - DAC960_V5_MemoryMailboxNewCommand(ControllerBaseAddress); - else DAC960_V5_HardwareMailboxNewCommand(ControllerBaseAddress); - } - Controller->PreviousCommandMailbox2 = Controller->PreviousCommandMailbox1; - Controller->PreviousCommandMailbox1 = NextCommandMailbox; - if (++NextCommandMailbox > Controller->LastCommandMailbox) - NextCommandMailbox = Controller->FirstCommandMailbox; - Controller->NextCommandMailbox = NextCommandMailbox; - break; - case DAC960_V4_Controller: - NextCommandMailbox = Controller->NextCommandMailbox; - DAC960_V4_WriteCommandMailbox(NextCommandMailbox, CommandMailbox); - if (Controller->PreviousCommandMailbox1->Words[0] == 0 || - Controller->PreviousCommandMailbox2->Words[0] == 0) - { - if (Controller->DualModeMemoryMailboxInterface) - DAC960_V4_MemoryMailboxNewCommand(ControllerBaseAddress); - else DAC960_V4_HardwareMailboxNewCommand(ControllerBaseAddress); - } - Controller->PreviousCommandMailbox2 = Controller->PreviousCommandMailbox1; - Controller->PreviousCommandMailbox1 = NextCommandMailbox; - if (++NextCommandMailbox > Controller->LastCommandMailbox) - NextCommandMailbox = Controller->FirstCommandMailbox; - Controller->NextCommandMailbox = NextCommandMailbox; - break; - case DAC960_V3_Controller: - while (DAC960_V3_MailboxFullP(ControllerBaseAddress)) - udelay(1); - DAC960_V3_WriteCommandMailbox(ControllerBaseAddress, CommandMailbox); - DAC960_V3_NewCommand(ControllerBaseAddress); - break; - } + DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; + DAC960_V2_CommandMailbox_T *NextCommandMailbox = + Controller->V2.NextCommandMailbox; + CommandMailbox->Common.CommandIdentifier = Command->CommandIdentifier; + DAC960_BA_WriteCommandMailbox(NextCommandMailbox, CommandMailbox); + if (Controller->V2.PreviousCommandMailbox1->Words[0] == 0 || + Controller->V2.PreviousCommandMailbox2->Words[0] == 0) + DAC960_BA_MemoryMailboxNewCommand(ControllerBaseAddress); + Controller->V2.PreviousCommandMailbox2 = + Controller->V2.PreviousCommandMailbox1; + Controller->V2.PreviousCommandMailbox1 = NextCommandMailbox; + if (++NextCommandMailbox > Controller->V2.LastCommandMailbox) + NextCommandMailbox = Controller->V2.FirstCommandMailbox; + Controller->V2.NextCommandMailbox = NextCommandMailbox; } /* - DAC960_ExecuteCommand executes Command and waits for completion. It - returns true on success and false on failure. + DAC960_LP_QueueCommand queues Command for DAC960 LP Series Controllers. */ -static boolean DAC960_ExecuteCommand(DAC960_Command_T *Command) +static void DAC960_LP_QueueCommand(DAC960_Command_T *Command) +{ + DAC960_Controller_T *Controller = Command->Controller; + void *ControllerBaseAddress = Controller->BaseAddress; + DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; + DAC960_V2_CommandMailbox_T *NextCommandMailbox = + Controller->V2.NextCommandMailbox; + CommandMailbox->Common.CommandIdentifier = Command->CommandIdentifier; + DAC960_LP_WriteCommandMailbox(NextCommandMailbox, CommandMailbox); + if (Controller->V2.PreviousCommandMailbox1->Words[0] == 0 || + Controller->V2.PreviousCommandMailbox2->Words[0] == 0) + DAC960_LP_MemoryMailboxNewCommand(ControllerBaseAddress); + Controller->V2.PreviousCommandMailbox2 = + Controller->V2.PreviousCommandMailbox1; + Controller->V2.PreviousCommandMailbox1 = NextCommandMailbox; + if (++NextCommandMailbox > Controller->V2.LastCommandMailbox) + NextCommandMailbox = Controller->V2.FirstCommandMailbox; + Controller->V2.NextCommandMailbox = NextCommandMailbox; +} + + +/* + DAC960_LA_QueueCommandDualMode queues Command for DAC960 LA Series + Controllers with Dual Mode Firmware. +*/ + +static void DAC960_LA_QueueCommandDualMode(DAC960_Command_T *Command) +{ + DAC960_Controller_T *Controller = Command->Controller; + void *ControllerBaseAddress = Controller->BaseAddress; + DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; + DAC960_V1_CommandMailbox_T *NextCommandMailbox = + Controller->V1.NextCommandMailbox; + CommandMailbox->Common.CommandIdentifier = Command->CommandIdentifier; + DAC960_LA_WriteCommandMailbox(NextCommandMailbox, CommandMailbox); + if (Controller->V1.PreviousCommandMailbox1->Words[0] == 0 || + Controller->V1.PreviousCommandMailbox2->Words[0] == 0) + DAC960_LA_MemoryMailboxNewCommand(ControllerBaseAddress); + Controller->V1.PreviousCommandMailbox2 = + Controller->V1.PreviousCommandMailbox1; + Controller->V1.PreviousCommandMailbox1 = NextCommandMailbox; + if (++NextCommandMailbox > Controller->V1.LastCommandMailbox) + NextCommandMailbox = Controller->V1.FirstCommandMailbox; + Controller->V1.NextCommandMailbox = NextCommandMailbox; +} + + +/* + DAC960_LA_QueueCommandSingleMode queues Command for DAC960 LA Series + Controllers with Single Mode Firmware. +*/ + +static void DAC960_LA_QueueCommandSingleMode(DAC960_Command_T *Command) +{ + DAC960_Controller_T *Controller = Command->Controller; + void *ControllerBaseAddress = Controller->BaseAddress; + DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; + DAC960_V1_CommandMailbox_T *NextCommandMailbox = + Controller->V1.NextCommandMailbox; + CommandMailbox->Common.CommandIdentifier = Command->CommandIdentifier; + DAC960_LA_WriteCommandMailbox(NextCommandMailbox, CommandMailbox); + if (Controller->V1.PreviousCommandMailbox1->Words[0] == 0 || + Controller->V1.PreviousCommandMailbox2->Words[0] == 0) + DAC960_LA_HardwareMailboxNewCommand(ControllerBaseAddress); + Controller->V1.PreviousCommandMailbox2 = + Controller->V1.PreviousCommandMailbox1; + Controller->V1.PreviousCommandMailbox1 = NextCommandMailbox; + if (++NextCommandMailbox > Controller->V1.LastCommandMailbox) + NextCommandMailbox = Controller->V1.FirstCommandMailbox; + Controller->V1.NextCommandMailbox = NextCommandMailbox; +} + + +/* + DAC960_PG_QueueCommandDualMode queues Command for DAC960 PG Series + Controllers with Dual Mode Firmware. +*/ + +static void DAC960_PG_QueueCommandDualMode(DAC960_Command_T *Command) +{ + DAC960_Controller_T *Controller = Command->Controller; + void *ControllerBaseAddress = Controller->BaseAddress; + DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; + DAC960_V1_CommandMailbox_T *NextCommandMailbox = + Controller->V1.NextCommandMailbox; + CommandMailbox->Common.CommandIdentifier = Command->CommandIdentifier; + DAC960_PG_WriteCommandMailbox(NextCommandMailbox, CommandMailbox); + if (Controller->V1.PreviousCommandMailbox1->Words[0] == 0 || + Controller->V1.PreviousCommandMailbox2->Words[0] == 0) + DAC960_PG_MemoryMailboxNewCommand(ControllerBaseAddress); + Controller->V1.PreviousCommandMailbox2 = + Controller->V1.PreviousCommandMailbox1; + Controller->V1.PreviousCommandMailbox1 = NextCommandMailbox; + if (++NextCommandMailbox > Controller->V1.LastCommandMailbox) + NextCommandMailbox = Controller->V1.FirstCommandMailbox; + Controller->V1.NextCommandMailbox = NextCommandMailbox; +} + + +/* + DAC960_PG_QueueCommandSingleMode queues Command for DAC960 PG Series + Controllers with Single Mode Firmware. +*/ + +static void DAC960_PG_QueueCommandSingleMode(DAC960_Command_T *Command) +{ + DAC960_Controller_T *Controller = Command->Controller; + void *ControllerBaseAddress = Controller->BaseAddress; + DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; + DAC960_V1_CommandMailbox_T *NextCommandMailbox = + Controller->V1.NextCommandMailbox; + CommandMailbox->Common.CommandIdentifier = Command->CommandIdentifier; + DAC960_PG_WriteCommandMailbox(NextCommandMailbox, CommandMailbox); + if (Controller->V1.PreviousCommandMailbox1->Words[0] == 0 || + Controller->V1.PreviousCommandMailbox2->Words[0] == 0) + DAC960_PG_HardwareMailboxNewCommand(ControllerBaseAddress); + Controller->V1.PreviousCommandMailbox2 = + Controller->V1.PreviousCommandMailbox1; + Controller->V1.PreviousCommandMailbox1 = NextCommandMailbox; + if (++NextCommandMailbox > Controller->V1.LastCommandMailbox) + NextCommandMailbox = Controller->V1.FirstCommandMailbox; + Controller->V1.NextCommandMailbox = NextCommandMailbox; +} + + +/* + DAC960_PD_QueueCommand queues Command for DAC960 PD Series Controllers. +*/ + +static void DAC960_PD_QueueCommand(DAC960_Command_T *Command) +{ + DAC960_Controller_T *Controller = Command->Controller; + void *ControllerBaseAddress = Controller->BaseAddress; + DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; + CommandMailbox->Common.CommandIdentifier = Command->CommandIdentifier; + while (DAC960_PD_MailboxFullP(ControllerBaseAddress)) + udelay(1); + DAC960_PD_WriteCommandMailbox(ControllerBaseAddress, CommandMailbox); + DAC960_PD_NewCommand(ControllerBaseAddress); +} + + +/* + DAC960_ExecuteCommand executes Command and waits for completion. +*/ + +static void DAC960_ExecuteCommand(DAC960_Command_T *Command) { DAC960_Controller_T *Controller = Command->Controller; DECLARE_MUTEX_LOCKED(Semaphore); @@ -270,227 +495,386 @@ static boolean DAC960_ExecuteCommand(DAC960_Command_T *Command) DAC960_AcquireControllerLock(Controller, &ProcessorFlags); DAC960_QueueCommand(Command); DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); - if (!in_interrupt()) - down(&Semaphore); - return Command->CommandStatus == DAC960_NormalCompletion; + if (in_interrupt()) return; + down(&Semaphore); } /* - DAC960_ExecuteType3 executes a DAC960 Type 3 Command and waits for - completion. It returns true on success and false on failure. + DAC960_V1_ExecuteType3 executes a DAC960 V1 Firmware Controller Type 3 + Command and waits for completion. It returns true on success and false + on failure. */ -static boolean DAC960_ExecuteType3(DAC960_Controller_T *Controller, - DAC960_CommandOpcode_T CommandOpcode, - void *DataPointer) +static boolean DAC960_V1_ExecuteType3(DAC960_Controller_T *Controller, + DAC960_V1_CommandOpcode_T CommandOpcode, + void *DataPointer) { DAC960_Command_T *Command = DAC960_AllocateCommand(Controller); - DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; - boolean Result; - DAC960_ClearCommand(Command); + DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; + DAC960_V1_CommandStatus_T CommandStatus; + DAC960_V1_ClearCommand(Command); Command->CommandType = DAC960_ImmediateCommand; CommandMailbox->Type3.CommandOpcode = CommandOpcode; CommandMailbox->Type3.BusAddress = Virtual_to_Bus(DataPointer); - Result = DAC960_ExecuteCommand(Command); + DAC960_ExecuteCommand(Command); + CommandStatus = Command->V1.CommandStatus; DAC960_DeallocateCommand(Command); - return Result; + return (CommandStatus == DAC960_V1_NormalCompletion); } /* - DAC960_ExecuteType3D executes a DAC960 Type 3D Command and waits for - completion. It returns true on success and false on failure. + DAC960_V1_ExecuteType3D executes a DAC960 V1 Firmware Controller Type 3D + Command and waits for completion. It returns true on success and false + on failure. */ -static boolean DAC960_ExecuteType3D(DAC960_Controller_T *Controller, - DAC960_CommandOpcode_T CommandOpcode, - unsigned char Channel, - unsigned char TargetID, - void *DataPointer) +static boolean DAC960_V1_ExecuteType3D(DAC960_Controller_T *Controller, + DAC960_V1_CommandOpcode_T CommandOpcode, + unsigned char Channel, + unsigned char TargetID, + void *DataPointer) { DAC960_Command_T *Command = DAC960_AllocateCommand(Controller); - DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; - boolean Result; - DAC960_ClearCommand(Command); + DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; + DAC960_V1_CommandStatus_T CommandStatus; + DAC960_V1_ClearCommand(Command); Command->CommandType = DAC960_ImmediateCommand; CommandMailbox->Type3D.CommandOpcode = CommandOpcode; CommandMailbox->Type3D.Channel = Channel; CommandMailbox->Type3D.TargetID = TargetID; CommandMailbox->Type3D.BusAddress = Virtual_to_Bus(DataPointer); - Result = DAC960_ExecuteCommand(Command); + DAC960_ExecuteCommand(Command); + CommandStatus = Command->V1.CommandStatus; DAC960_DeallocateCommand(Command); - return Result; + return (CommandStatus == DAC960_V1_NormalCompletion); } /* - DAC960_ReportErrorStatus reports Controller BIOS Messages passed through - the Error Status Register when the driver performs the BIOS handshaking. - It returns true for fatal errors and false otherwise. + DAC960_V2_GeneralInfo executes a DAC960 V2 Firmware General Information + Reading IOCTL Command and waits for completion. It returns true on success + and false on failure. */ -static boolean DAC960_ReportErrorStatus(DAC960_Controller_T *Controller, - unsigned char ErrorStatus, - unsigned char Parameter0, - unsigned char Parameter1) +static boolean DAC960_V2_GeneralInfo(DAC960_Controller_T *Controller, + DAC960_V2_IOCTL_Opcode_T IOCTL_Opcode, + void *DataPointer, + unsigned int DataByteCount) { - switch (ErrorStatus) - { - case 0x00: - DAC960_Notice("Physical Drive %d:%d Not Responding\n", - Controller, Parameter1, Parameter0); - break; - case 0x08: - if (Controller->DriveSpinUpMessageDisplayed) break; - DAC960_Notice("Spinning Up Drives\n", Controller); - Controller->DriveSpinUpMessageDisplayed = true; - break; - case 0x30: - DAC960_Notice("Configuration Checksum Error\n", Controller); - break; - case 0x60: - DAC960_Notice("Mirror Race Recovery Failed\n", Controller); - break; - case 0x70: - DAC960_Notice("Mirror Race Recovery In Progress\n", Controller); - break; - case 0x90: - DAC960_Notice("Physical Drive %d:%d COD Mismatch\n", - Controller, Parameter1, Parameter0); - break; - case 0xA0: - DAC960_Notice("Logical Drive Installation Aborted\n", Controller); - break; - case 0xB0: - DAC960_Notice("Mirror Race On A Critical Logical Drive\n", Controller); - break; - case 0xD0: - DAC960_Notice("New Controller Configuration Found\n", Controller); - break; - case 0xF0: - DAC960_Error("Fatal Memory Parity Error for Controller at\n", Controller); - return true; - default: - DAC960_Error("Unknown Initialization Error %02X for Controller at\n", - Controller, ErrorStatus); - return true; - } - return false; + DAC960_Command_T *Command = DAC960_AllocateCommand(Controller); + DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; + DAC960_V2_CommandStatus_T CommandStatus; + DAC960_V2_ClearCommand(Command); + Command->CommandType = DAC960_ImmediateCommand; + CommandMailbox->Common.CommandOpcode = DAC960_V2_IOCTL; + CommandMailbox->Common.CommandControlBits + .DataTransferControllerToHost = true; + CommandMailbox->Common.CommandControlBits + .NoAutoRequestSense = true; + CommandMailbox->Common.DataTransferSize = DataByteCount; + CommandMailbox->Common.IOCTL_Opcode = IOCTL_Opcode; + CommandMailbox->Common.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Virtual_to_Bus(DataPointer); + CommandMailbox->Common.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->Common.DataTransferSize; + DAC960_ExecuteCommand(Command); + CommandStatus = Command->V2.CommandStatus; + DAC960_DeallocateCommand(Command); + return (CommandStatus == DAC960_V2_NormalCompletion); } /* - DAC960_EnableMemoryMailboxInterface enables the Memory Mailbox Interface. + DAC960_V2_ControllerInfo executes a DAC960 V2 Firmware Controller + Information Reading IOCTL Command and waits for completion. It returns + true on success and false on failure. */ -static boolean DAC960_EnableMemoryMailboxInterface(DAC960_Controller_T - *Controller) +static boolean DAC960_V2_ControllerInfo(DAC960_Controller_T *Controller, + DAC960_V2_IOCTL_Opcode_T IOCTL_Opcode, + void *DataPointer, + unsigned int DataByteCount) +{ + DAC960_Command_T *Command = DAC960_AllocateCommand(Controller); + DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; + DAC960_V2_CommandStatus_T CommandStatus; + DAC960_V2_ClearCommand(Command); + Command->CommandType = DAC960_ImmediateCommand; + CommandMailbox->ControllerInfo.CommandOpcode = DAC960_V2_IOCTL; + CommandMailbox->ControllerInfo.CommandControlBits + .DataTransferControllerToHost = true; + CommandMailbox->ControllerInfo.CommandControlBits + .NoAutoRequestSense = true; + CommandMailbox->ControllerInfo.DataTransferSize = DataByteCount; + CommandMailbox->ControllerInfo.ControllerNumber = 0; + CommandMailbox->ControllerInfo.IOCTL_Opcode = IOCTL_Opcode; + CommandMailbox->ControllerInfo.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Virtual_to_Bus(DataPointer); + CommandMailbox->ControllerInfo.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->ControllerInfo.DataTransferSize; + DAC960_ExecuteCommand(Command); + CommandStatus = Command->V2.CommandStatus; + DAC960_DeallocateCommand(Command); + return (CommandStatus == DAC960_V2_NormalCompletion); +} + + +/* + DAC960_V2_LogicalDeviceInfo executes a DAC960 V2 Firmware Controller Logical + Device Information Reading IOCTL Command and waits for completion. It + returns true on success and false on failure. +*/ + +static boolean DAC960_V2_LogicalDeviceInfo(DAC960_Controller_T *Controller, + DAC960_V2_IOCTL_Opcode_T + IOCTL_Opcode, + unsigned short + LogicalDeviceNumber, + void *DataPointer, + unsigned int DataByteCount) +{ + DAC960_Command_T *Command = DAC960_AllocateCommand(Controller); + DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; + DAC960_V2_CommandStatus_T CommandStatus; + DAC960_V2_ClearCommand(Command); + Command->CommandType = DAC960_ImmediateCommand; + CommandMailbox->LogicalDeviceInfo.CommandOpcode = DAC960_V2_IOCTL; + CommandMailbox->LogicalDeviceInfo.CommandControlBits + .DataTransferControllerToHost = true; + CommandMailbox->LogicalDeviceInfo.CommandControlBits + .NoAutoRequestSense = true; + CommandMailbox->LogicalDeviceInfo.DataTransferSize = DataByteCount; + CommandMailbox->LogicalDeviceInfo.LogicalDevice.LogicalDeviceNumber = + LogicalDeviceNumber; + CommandMailbox->LogicalDeviceInfo.IOCTL_Opcode = IOCTL_Opcode; + CommandMailbox->LogicalDeviceInfo.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Virtual_to_Bus(DataPointer); + CommandMailbox->LogicalDeviceInfo.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->LogicalDeviceInfo.DataTransferSize; + DAC960_ExecuteCommand(Command); + CommandStatus = Command->V2.CommandStatus; + DAC960_DeallocateCommand(Command); + return (CommandStatus == DAC960_V2_NormalCompletion); +} + + +/* + DAC960_V2_PhysicalDeviceInfo executes a DAC960 V2 Firmware Controller Physical + Device Information Reading IOCTL Command and waits for completion. It + returns true on success and false on failure. +*/ + +static boolean DAC960_V2_PhysicalDeviceInfo(DAC960_Controller_T *Controller, + DAC960_V2_IOCTL_Opcode_T + IOCTL_Opcode, + unsigned char Channel, + unsigned char TargetID, + unsigned char LogicalUnit, + void *DataPointer, + unsigned int DataByteCount) +{ + DAC960_Command_T *Command = DAC960_AllocateCommand(Controller); + DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; + DAC960_V2_CommandStatus_T CommandStatus; + DAC960_V2_ClearCommand(Command); + Command->CommandType = DAC960_ImmediateCommand; + CommandMailbox->PhysicalDeviceInfo.CommandOpcode = DAC960_V2_IOCTL; + CommandMailbox->PhysicalDeviceInfo.CommandControlBits + .DataTransferControllerToHost = true; + CommandMailbox->PhysicalDeviceInfo.CommandControlBits + .NoAutoRequestSense = true; + CommandMailbox->PhysicalDeviceInfo.DataTransferSize = DataByteCount; + CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.LogicalUnit = LogicalUnit; + CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.TargetID = TargetID; + CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.Channel = Channel; + CommandMailbox->PhysicalDeviceInfo.IOCTL_Opcode = IOCTL_Opcode; + CommandMailbox->PhysicalDeviceInfo.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Virtual_to_Bus(DataPointer); + CommandMailbox->PhysicalDeviceInfo.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->PhysicalDeviceInfo.DataTransferSize; + DAC960_ExecuteCommand(Command); + CommandStatus = Command->V2.CommandStatus; + DAC960_DeallocateCommand(Command); + return (CommandStatus == DAC960_V2_NormalCompletion); +} + + +/* + DAC960_V2_DeviceOperation executes a DAC960 V2 Firmware Controller Device + Operation IOCTL Command and waits for completion. It returns true on + success and false on failure. +*/ + +static boolean DAC960_V2_DeviceOperation(DAC960_Controller_T *Controller, + DAC960_V2_IOCTL_Opcode_T IOCTL_Opcode, + DAC960_V2_OperationDevice_T + OperationDevice) +{ + DAC960_Command_T *Command = DAC960_AllocateCommand(Controller); + DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; + DAC960_V2_CommandStatus_T CommandStatus; + DAC960_V2_ClearCommand(Command); + Command->CommandType = DAC960_ImmediateCommand; + CommandMailbox->DeviceOperation.CommandOpcode = DAC960_V2_IOCTL; + CommandMailbox->DeviceOperation.CommandControlBits + .DataTransferControllerToHost = true; + CommandMailbox->DeviceOperation.CommandControlBits + .NoAutoRequestSense = true; + CommandMailbox->DeviceOperation.IOCTL_Opcode = IOCTL_Opcode; + CommandMailbox->DeviceOperation.OperationDevice = OperationDevice; + DAC960_ExecuteCommand(Command); + CommandStatus = Command->V2.CommandStatus; + DAC960_DeallocateCommand(Command); + return (CommandStatus == DAC960_V2_NormalCompletion); +} + + +/* + DAC960_V1_EnableMemoryMailboxInterface enables the Memory Mailbox Interface + for DAC960 V1 Firmware Controllers. +*/ + +static boolean DAC960_V1_EnableMemoryMailboxInterface(DAC960_Controller_T + *Controller) { void *ControllerBaseAddress = Controller->BaseAddress; - DAC960_CommandMailbox_T *CommandMailboxesMemory; - DAC960_StatusMailbox_T *StatusMailboxesMemory; - DAC960_CommandMailbox_T CommandMailbox; - DAC960_CommandStatus_T CommandStatus; + DAC960_V1_CommandMailbox_T *CommandMailboxesMemory; + DAC960_V1_StatusMailbox_T *StatusMailboxesMemory; + DAC960_V1_CommandMailbox_T CommandMailbox; + DAC960_V1_CommandStatus_T CommandStatus; + unsigned long MemoryMailboxPagesAddress; + unsigned long MemoryMailboxPagesOrder; + unsigned long MemoryMailboxPagesSize; void *SavedMemoryMailboxesAddress = NULL; short NextCommandMailboxIndex = 0; short NextStatusMailboxIndex = 0; int TimeoutCounter = 1000000, i; - if (Controller->ControllerType == DAC960_V5_Controller) - DAC960_V5_RestoreMemoryMailboxInfo(Controller, + MemoryMailboxPagesOrder = 0; + MemoryMailboxPagesSize = + DAC960_V1_CommandMailboxCount * sizeof(DAC960_V1_CommandMailbox_T) + + DAC960_V1_StatusMailboxCount * sizeof(DAC960_V1_StatusMailbox_T); + while (MemoryMailboxPagesSize > PAGE_SIZE << MemoryMailboxPagesOrder) + MemoryMailboxPagesOrder++; + if (Controller->HardwareType == DAC960_LA_Controller) + DAC960_LA_RestoreMemoryMailboxInfo(Controller, &SavedMemoryMailboxesAddress, &NextCommandMailboxIndex, &NextStatusMailboxIndex); - else DAC960_V4_RestoreMemoryMailboxInfo(Controller, + else DAC960_PG_RestoreMemoryMailboxInfo(Controller, &SavedMemoryMailboxesAddress, &NextCommandMailboxIndex, &NextStatusMailboxIndex); if (SavedMemoryMailboxesAddress == NULL) - CommandMailboxesMemory = - (DAC960_CommandMailbox_T *) __get_free_pages(GFP_KERNEL, 1); + { + MemoryMailboxPagesAddress = + __get_free_pages(GFP_KERNEL, MemoryMailboxPagesOrder); + Controller->MemoryMailboxPagesAddress = MemoryMailboxPagesAddress; + CommandMailboxesMemory = + (DAC960_V1_CommandMailbox_T *) MemoryMailboxPagesAddress; + } else CommandMailboxesMemory = SavedMemoryMailboxesAddress; - memset(CommandMailboxesMemory, 0, PAGE_SIZE << 1); - Controller->FirstCommandMailbox = CommandMailboxesMemory; - CommandMailboxesMemory += DAC960_CommandMailboxCount - 1; - Controller->LastCommandMailbox = CommandMailboxesMemory; - Controller->NextCommandMailbox = - &Controller->FirstCommandMailbox[NextCommandMailboxIndex]; + if (CommandMailboxesMemory == NULL) return false; + Controller->MemoryMailboxPagesOrder = MemoryMailboxPagesOrder; + memset(CommandMailboxesMemory, 0, MemoryMailboxPagesSize); + Controller->V1.FirstCommandMailbox = CommandMailboxesMemory; + CommandMailboxesMemory += DAC960_V1_CommandMailboxCount - 1; + Controller->V1.LastCommandMailbox = CommandMailboxesMemory; + Controller->V1.NextCommandMailbox = + &Controller->V1.FirstCommandMailbox[NextCommandMailboxIndex]; if (--NextCommandMailboxIndex < 0) - NextCommandMailboxIndex = DAC960_CommandMailboxCount - 1; - Controller->PreviousCommandMailbox1 = - &Controller->FirstCommandMailbox[NextCommandMailboxIndex]; + NextCommandMailboxIndex = DAC960_V1_CommandMailboxCount - 1; + Controller->V1.PreviousCommandMailbox1 = + &Controller->V1.FirstCommandMailbox[NextCommandMailboxIndex]; if (--NextCommandMailboxIndex < 0) - NextCommandMailboxIndex = DAC960_CommandMailboxCount - 1; - Controller->PreviousCommandMailbox2 = - &Controller->FirstCommandMailbox[NextCommandMailboxIndex]; + NextCommandMailboxIndex = DAC960_V1_CommandMailboxCount - 1; + Controller->V1.PreviousCommandMailbox2 = + &Controller->V1.FirstCommandMailbox[NextCommandMailboxIndex]; StatusMailboxesMemory = - (DAC960_StatusMailbox_T *) (CommandMailboxesMemory + 1); - Controller->FirstStatusMailbox = StatusMailboxesMemory; - StatusMailboxesMemory += DAC960_StatusMailboxCount - 1; - Controller->LastStatusMailbox = StatusMailboxesMemory; - Controller->NextStatusMailbox = - &Controller->FirstStatusMailbox[NextStatusMailboxIndex]; + (DAC960_V1_StatusMailbox_T *) (CommandMailboxesMemory + 1); + Controller->V1.FirstStatusMailbox = StatusMailboxesMemory; + StatusMailboxesMemory += DAC960_V1_StatusMailboxCount - 1; + Controller->V1.LastStatusMailbox = StatusMailboxesMemory; + Controller->V1.NextStatusMailbox = + &Controller->V1.FirstStatusMailbox[NextStatusMailboxIndex]; if (SavedMemoryMailboxesAddress != NULL) return true; /* Enable the Memory Mailbox Interface. */ - Controller->DualModeMemoryMailboxInterface = true; + Controller->V1.DualModeMemoryMailboxInterface = true; CommandMailbox.TypeX.CommandOpcode = 0x2B; CommandMailbox.TypeX.CommandIdentifier = 0; CommandMailbox.TypeX.CommandOpcode2 = 0x14; CommandMailbox.TypeX.CommandMailboxesBusAddress = - Virtual_to_Bus(Controller->FirstCommandMailbox); + Virtual_to_Bus(Controller->V1.FirstCommandMailbox); CommandMailbox.TypeX.StatusMailboxesBusAddress = - Virtual_to_Bus(Controller->FirstStatusMailbox); + Virtual_to_Bus(Controller->V1.FirstStatusMailbox); for (i = 0; i < 2; i++) - switch (Controller->ControllerType) + switch (Controller->HardwareType) { - case DAC960_V5_Controller: + case DAC960_LA_Controller: while (--TimeoutCounter >= 0) { - if (!DAC960_V5_HardwareMailboxFullP(ControllerBaseAddress)) + if (!DAC960_LA_HardwareMailboxFullP(ControllerBaseAddress)) break; udelay(10); } if (TimeoutCounter < 0) return false; - DAC960_V5_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox); - DAC960_V5_HardwareMailboxNewCommand(ControllerBaseAddress); + DAC960_LA_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox); + DAC960_LA_HardwareMailboxNewCommand(ControllerBaseAddress); while (--TimeoutCounter >= 0) { - if (DAC960_V5_HardwareMailboxStatusAvailableP( + if (DAC960_LA_HardwareMailboxStatusAvailableP( ControllerBaseAddress)) break; udelay(10); } if (TimeoutCounter < 0) return false; - CommandStatus = DAC960_V5_ReadStatusRegister(ControllerBaseAddress); - DAC960_V5_AcknowledgeHardwareMailboxInterrupt(ControllerBaseAddress); - DAC960_V5_AcknowledgeHardwareMailboxStatus(ControllerBaseAddress); - if (CommandStatus == DAC960_NormalCompletion) return true; - Controller->DualModeMemoryMailboxInterface = false; + CommandStatus = DAC960_LA_ReadStatusRegister(ControllerBaseAddress); + DAC960_LA_AcknowledgeHardwareMailboxInterrupt(ControllerBaseAddress); + DAC960_LA_AcknowledgeHardwareMailboxStatus(ControllerBaseAddress); + if (CommandStatus == DAC960_V1_NormalCompletion) return true; + Controller->V1.DualModeMemoryMailboxInterface = false; CommandMailbox.TypeX.CommandOpcode2 = 0x10; break; - case DAC960_V4_Controller: + case DAC960_PG_Controller: while (--TimeoutCounter >= 0) { - if (!DAC960_V4_HardwareMailboxFullP(ControllerBaseAddress)) + if (!DAC960_PG_HardwareMailboxFullP(ControllerBaseAddress)) break; udelay(10); } if (TimeoutCounter < 0) return false; - DAC960_V4_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox); - DAC960_V4_HardwareMailboxNewCommand(ControllerBaseAddress); + DAC960_PG_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox); + DAC960_PG_HardwareMailboxNewCommand(ControllerBaseAddress); while (--TimeoutCounter >= 0) { - if (DAC960_V4_HardwareMailboxStatusAvailableP( + if (DAC960_PG_HardwareMailboxStatusAvailableP( ControllerBaseAddress)) break; udelay(10); } if (TimeoutCounter < 0) return false; - CommandStatus = DAC960_V4_ReadStatusRegister(ControllerBaseAddress); - DAC960_V4_AcknowledgeHardwareMailboxInterrupt(ControllerBaseAddress); - DAC960_V4_AcknowledgeHardwareMailboxStatus(ControllerBaseAddress); - if (CommandStatus == DAC960_NormalCompletion) return true; - Controller->DualModeMemoryMailboxInterface = false; + CommandStatus = DAC960_PG_ReadStatusRegister(ControllerBaseAddress); + DAC960_PG_AcknowledgeHardwareMailboxInterrupt(ControllerBaseAddress); + DAC960_PG_AcknowledgeHardwareMailboxStatus(ControllerBaseAddress); + if (CommandStatus == DAC960_V1_NormalCompletion) return true; + Controller->V1.DualModeMemoryMailboxInterface = false; CommandMailbox.TypeX.CommandOpcode2 = 0x10; break; default: @@ -501,287 +885,165 @@ static boolean DAC960_EnableMemoryMailboxInterface(DAC960_Controller_T /* - DAC960_DetectControllers detects DAC960 PCI RAID Controllers by interrogating - the PCI Configuration Space for Controller Type. + DAC960_V2_EnableMemoryMailboxInterface enables the Memory Mailbox Interface + for DAC960 V2 Firmware Controllers. */ -static void DAC960_DetectControllers(DAC960_ControllerType_T ControllerType) +static boolean DAC960_V2_EnableMemoryMailboxInterface(DAC960_Controller_T + *Controller) { - unsigned short VendorID = 0, DeviceID = 0; - unsigned int MemoryWindowSize = 0; - PCI_Device_T *PCI_Device = NULL; - switch (ControllerType) + void *ControllerBaseAddress = Controller->BaseAddress; + DAC960_V2_CommandMailbox_T *CommandMailboxesMemory; + DAC960_V2_StatusMailbox_T *StatusMailboxesMemory; + DAC960_V2_CommandMailbox_T CommandMailbox; + DAC960_V2_CommandStatus_T CommandStatus = 0; + unsigned long MemoryMailboxPagesAddress; + unsigned long MemoryMailboxPagesOrder; + unsigned long MemoryMailboxPagesSize; + MemoryMailboxPagesOrder = 0; + MemoryMailboxPagesSize = + DAC960_V2_CommandMailboxCount * sizeof(DAC960_V2_CommandMailbox_T) + + DAC960_V2_StatusMailboxCount * sizeof(DAC960_V2_StatusMailbox_T) + + sizeof(DAC960_V2_HealthStatusBuffer_T); + while (MemoryMailboxPagesSize > PAGE_SIZE << MemoryMailboxPagesOrder) + MemoryMailboxPagesOrder++; + MemoryMailboxPagesAddress = + __get_free_pages(GFP_KERNEL, MemoryMailboxPagesOrder); + Controller->MemoryMailboxPagesAddress = MemoryMailboxPagesAddress; + CommandMailboxesMemory = + (DAC960_V2_CommandMailbox_T *) MemoryMailboxPagesAddress; + if (CommandMailboxesMemory == NULL) return false; + Controller->MemoryMailboxPagesOrder = MemoryMailboxPagesOrder; + memset(CommandMailboxesMemory, 0, MemoryMailboxPagesSize); + Controller->V2.FirstCommandMailbox = CommandMailboxesMemory; + CommandMailboxesMemory += DAC960_V2_CommandMailboxCount - 1; + Controller->V2.LastCommandMailbox = CommandMailboxesMemory; + Controller->V2.NextCommandMailbox = Controller->V2.FirstCommandMailbox; + Controller->V2.PreviousCommandMailbox1 = Controller->V2.LastCommandMailbox; + Controller->V2.PreviousCommandMailbox2 = + Controller->V2.LastCommandMailbox - 1; + StatusMailboxesMemory = + (DAC960_V2_StatusMailbox_T *) (CommandMailboxesMemory + 1); + Controller->V2.FirstStatusMailbox = StatusMailboxesMemory; + StatusMailboxesMemory += DAC960_V2_StatusMailboxCount - 1; + Controller->V2.LastStatusMailbox = StatusMailboxesMemory; + Controller->V2.NextStatusMailbox = Controller->V2.FirstStatusMailbox; + Controller->V2.HealthStatusBuffer = + (DAC960_V2_HealthStatusBuffer_T *) (StatusMailboxesMemory + 1); + /* Enable the Memory Mailbox Interface. */ + memset(&CommandMailbox, 0, sizeof(DAC960_V2_CommandMailbox_T)); + CommandMailbox.SetMemoryMailbox.CommandIdentifier = 1; + CommandMailbox.SetMemoryMailbox.CommandOpcode = DAC960_V2_IOCTL; + CommandMailbox.SetMemoryMailbox.CommandControlBits.NoAutoRequestSense = true; + CommandMailbox.SetMemoryMailbox.FirstCommandMailboxSizeKB = + (DAC960_V2_CommandMailboxCount * sizeof(DAC960_V2_CommandMailbox_T)) >> 10; + CommandMailbox.SetMemoryMailbox.FirstStatusMailboxSizeKB = + (DAC960_V2_StatusMailboxCount * sizeof(DAC960_V2_StatusMailbox_T)) >> 10; + CommandMailbox.SetMemoryMailbox.SecondCommandMailboxSizeKB = 0; + CommandMailbox.SetMemoryMailbox.SecondStatusMailboxSizeKB = 0; + CommandMailbox.SetMemoryMailbox.RequestSenseSize = 0; + CommandMailbox.SetMemoryMailbox.IOCTL_Opcode = DAC960_V2_SetMemoryMailbox; + CommandMailbox.SetMemoryMailbox.HealthStatusBufferSizeKB = 1; + CommandMailbox.SetMemoryMailbox.HealthStatusBufferBusAddress = + Virtual_to_Bus(Controller->V2.HealthStatusBuffer); + CommandMailbox.SetMemoryMailbox.FirstCommandMailboxBusAddress = + Virtual_to_Bus(Controller->V2.FirstCommandMailbox); + CommandMailbox.SetMemoryMailbox.FirstStatusMailboxBusAddress = + Virtual_to_Bus(Controller->V2.FirstStatusMailbox); + switch (Controller->HardwareType) { - case DAC960_V5_Controller: - VendorID = PCI_VENDOR_ID_DEC; - DeviceID = PCI_DEVICE_ID_DEC_21285; - MemoryWindowSize = DAC960_V5_RegisterWindowSize; + case DAC960_BA_Controller: + while (DAC960_BA_HardwareMailboxFullP(ControllerBaseAddress)) + udelay(1); + DAC960_BA_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox); + DAC960_BA_HardwareMailboxNewCommand(ControllerBaseAddress); + while (!DAC960_BA_HardwareMailboxStatusAvailableP(ControllerBaseAddress)) + udelay(1); + CommandStatus = DAC960_BA_ReadCommandStatus(ControllerBaseAddress); + DAC960_BA_AcknowledgeHardwareMailboxInterrupt(ControllerBaseAddress); + DAC960_BA_AcknowledgeHardwareMailboxStatus(ControllerBaseAddress); break; - case DAC960_V4_Controller: - VendorID = PCI_VENDOR_ID_MYLEX; - DeviceID = PCI_DEVICE_ID_MYLEX_DAC960P_V4; - MemoryWindowSize = DAC960_V4_RegisterWindowSize; + case DAC960_LP_Controller: + while (DAC960_LP_HardwareMailboxFullP(ControllerBaseAddress)) + udelay(1); + DAC960_LP_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox); + DAC960_LP_HardwareMailboxNewCommand(ControllerBaseAddress); + while (!DAC960_LP_HardwareMailboxStatusAvailableP(ControllerBaseAddress)) + udelay(1); + CommandStatus = DAC960_LP_ReadCommandStatus(ControllerBaseAddress); + DAC960_LP_AcknowledgeHardwareMailboxInterrupt(ControllerBaseAddress); + DAC960_LP_AcknowledgeHardwareMailboxStatus(ControllerBaseAddress); break; - case DAC960_V3_Controller: - VendorID = PCI_VENDOR_ID_MYLEX; - DeviceID = PCI_DEVICE_ID_MYLEX_DAC960P_V3; - MemoryWindowSize = DAC960_V3_RegisterWindowSize; + default: break; } - while ((PCI_Device = pci_find_device(VendorID, DeviceID, PCI_Device)) != NULL) - { - DAC960_Controller_T *Controller = (DAC960_Controller_T *) - kmalloc(sizeof(DAC960_Controller_T), GFP_ATOMIC); - DAC960_IO_Address_T IO_Address = 0; - DAC960_PCI_Address_T PCI_Address = 0; - unsigned char Bus = PCI_Device->bus->number; - unsigned char DeviceFunction = PCI_Device->devfn; - unsigned char Device = DeviceFunction >> 3; - unsigned char Function = DeviceFunction & 0x7; - unsigned int IRQ_Channel = PCI_Device->irq; - unsigned long BaseAddress0 = pci_resource_start (PCI_Device, 0); - unsigned long BaseAddress1 = pci_resource_start (PCI_Device, 1); - unsigned short SubsystemVendorID, SubsystemDeviceID; - int CommandIdentifier; - unsigned char ErrorStatus, Parameter0, Parameter1; - void *BaseAddress; - - - if (pci_enable_device(PCI_Device)) - goto Ignore; - - SubsystemVendorID = PCI_Device->subsystem_vendor; - SubsystemDeviceID = PCI_Device->subsystem_device; - switch (ControllerType) - { - case DAC960_V5_Controller: - if (!(SubsystemVendorID == PCI_VENDOR_ID_MYLEX && - SubsystemDeviceID == PCI_DEVICE_ID_MYLEX_DAC960P_V5)) - goto Ignore; - PCI_Address = BaseAddress0; - break; - case DAC960_V4_Controller: - PCI_Address = BaseAddress0; - break; - case DAC960_V3_Controller: - IO_Address = BaseAddress0; - PCI_Address = BaseAddress1; - break; - } - if (DAC960_ControllerCount == DAC960_MaxControllers) - { - DAC960_Error("More than %d DAC960 Controllers detected - " - "ignoring from Controller at\n", - NULL, DAC960_MaxControllers); - goto Ignore; - } - if (Controller == NULL) - { - DAC960_Error("Unable to allocate Controller structure for " - "Controller at\n", NULL); - goto Ignore; - } - memset(Controller, 0, sizeof(DAC960_Controller_T)); - init_waitqueue_head(&Controller->CommandWaitQueue); - Controller->ControllerNumber = DAC960_ControllerCount; - DAC960_Controllers[DAC960_ControllerCount++] = Controller; - DAC960_AnnounceDriver(Controller); - Controller->ControllerType = ControllerType; - Controller->IO_Address = IO_Address; - Controller->PCI_Address = PCI_Address; - Controller->Bus = Bus; - Controller->Device = Device; - Controller->Function = Function; - sprintf(Controller->ControllerName, "c%d", Controller->ControllerNumber); - /* - Map the Controller Register Window. - */ - if (MemoryWindowSize < PAGE_SIZE) - MemoryWindowSize = PAGE_SIZE; - Controller->MemoryMappedAddress = - ioremap_nocache(PCI_Address & PAGE_MASK, MemoryWindowSize); - Controller->BaseAddress = - Controller->MemoryMappedAddress + (PCI_Address & ~PAGE_MASK); - if (Controller->MemoryMappedAddress == NULL) - { - DAC960_Error("Unable to map Controller Register Window for " - "Controller at\n", Controller); - goto Failure; - } - BaseAddress = Controller->BaseAddress; - switch (ControllerType) - { - case DAC960_V5_Controller: - DAC960_V5_DisableInterrupts(BaseAddress); - DAC960_V5_AcknowledgeHardwareMailboxStatus(BaseAddress); - udelay(1000); - while (DAC960_V5_InitializationInProgressP(BaseAddress)) - { - if (DAC960_V5_ReadErrorStatus(BaseAddress, &ErrorStatus, - &Parameter0, &Parameter1) && - DAC960_ReportErrorStatus(Controller, ErrorStatus, - Parameter0, Parameter1)) - goto Failure; - udelay(10); - } - if (!DAC960_EnableMemoryMailboxInterface(Controller)) - { - DAC960_Error("Unable to Enable Memory Mailbox Interface " - "for Controller at\n", Controller); - goto Failure; - } - DAC960_V5_EnableInterrupts(BaseAddress); - break; - case DAC960_V4_Controller: - DAC960_V4_DisableInterrupts(BaseAddress); - DAC960_V4_AcknowledgeHardwareMailboxStatus(BaseAddress); - udelay(1000); - while (DAC960_V4_InitializationInProgressP(BaseAddress)) - { - if (DAC960_V4_ReadErrorStatus(BaseAddress, &ErrorStatus, - &Parameter0, &Parameter1) && - DAC960_ReportErrorStatus(Controller, ErrorStatus, - Parameter0, Parameter1)) - goto Failure; - udelay(10); - } - if (!DAC960_EnableMemoryMailboxInterface(Controller)) - { - DAC960_Error("Unable to Enable Memory Mailbox Interface " - "for Controller at\n", Controller); - goto Failure; - } - DAC960_V4_EnableInterrupts(BaseAddress); - break; - case DAC960_V3_Controller: - request_region(Controller->IO_Address, 0x80, - Controller->FullModelName); - DAC960_V3_DisableInterrupts(BaseAddress); - DAC960_V3_AcknowledgeStatus(BaseAddress); - udelay(1000); - while (DAC960_V3_InitializationInProgressP(BaseAddress)) - { - if (DAC960_V3_ReadErrorStatus(BaseAddress, &ErrorStatus, - &Parameter0, &Parameter1) && - DAC960_ReportErrorStatus(Controller, ErrorStatus, - Parameter0, Parameter1)) - goto Failure; - udelay(10); - } - DAC960_V3_EnableInterrupts(BaseAddress); - break; - } - /* - Acquire shared access to the IRQ Channel. - */ - if (IRQ_Channel == 0) - { - DAC960_Error("IRQ Channel %d illegal for Controller at\n", - Controller, IRQ_Channel); - goto Failure; - } - strcpy(Controller->FullModelName, "DAC960"); - if (request_irq(IRQ_Channel, DAC960_InterruptHandler, - SA_SHIRQ, Controller->FullModelName, Controller) < 0) - { - DAC960_Error("Unable to acquire IRQ Channel %d for Controller at\n", - Controller, IRQ_Channel); - goto Failure; - } - Controller->IRQ_Channel = IRQ_Channel; - DAC960_ActiveControllerCount++; - for (CommandIdentifier = 0; - CommandIdentifier < DAC960_MaxChannels; - CommandIdentifier++) - { - Controller->Commands[CommandIdentifier].Controller = Controller; - Controller->Commands[CommandIdentifier].Next = - Controller->FreeCommands; - Controller->FreeCommands = &Controller->Commands[CommandIdentifier]; - } - continue; - Failure: - if (IO_Address == 0) - DAC960_Error("PCI Bus %d Device %d Function %d I/O Address N/A " - "PCI Address 0x%X\n", Controller, - Bus, Device, Function, PCI_Address); - else DAC960_Error("PCI Bus %d Device %d Function %d I/O Address " - "0x%X PCI Address 0x%X\n", Controller, - Bus, Device, Function, IO_Address, PCI_Address); - if (Controller == NULL) break; - if (Controller->MemoryMappedAddress != NULL) - iounmap(Controller->MemoryMappedAddress); - DAC960_Controllers[Controller->ControllerNumber] = NULL; - if (Controller->IRQ_Channel > 0) - free_irq(IRQ_Channel, Controller); - Ignore: - kfree(Controller); - } + return (CommandStatus == DAC960_V2_NormalCompletion); } /* - DAC960_ReadControllerConfiguration reads the Configuration Information - from Controller and initializes the Controller structure. + DAC960_V1_ReadControllerConfiguration reads the Configuration Information + from DAC960 V1 Firmware Controllers and initializes the Controller structure. */ -static boolean DAC960_ReadControllerConfiguration(DAC960_Controller_T - *Controller) +static boolean DAC960_V1_ReadControllerConfiguration(DAC960_Controller_T + *Controller) { - DAC960_Enquiry2_T Enquiry2; - DAC960_Config2_T Config2; + DAC960_V1_Enquiry2_T Enquiry2; + DAC960_V1_Config2_T Config2; int LogicalDriveNumber, Channel, TargetID; - if (!DAC960_ExecuteType3(Controller, DAC960_Enquiry, - &Controller->Enquiry[0])) + if (!DAC960_V1_ExecuteType3(Controller, DAC960_V1_Enquiry, + &Controller->V1.Enquiry)) return DAC960_Failure(Controller, "ENQUIRY"); - if (!DAC960_ExecuteType3(Controller, DAC960_Enquiry2, &Enquiry2)) + if (!DAC960_V1_ExecuteType3(Controller, DAC960_V1_Enquiry2, &Enquiry2)) return DAC960_Failure(Controller, "ENQUIRY2"); - if (!DAC960_ExecuteType3(Controller, DAC960_ReadConfig2, &Config2)) + if (!DAC960_V1_ExecuteType3(Controller, DAC960_V1_ReadConfig2, &Config2)) return DAC960_Failure(Controller, "READ CONFIG2"); - if (!DAC960_ExecuteType3(Controller, DAC960_GetLogicalDriveInformation, - &Controller->LogicalDriveInformation[0])) + if (!DAC960_V1_ExecuteType3(Controller, DAC960_V1_GetLogicalDriveInformation, + &Controller->V1.LogicalDriveInformation)) return DAC960_Failure(Controller, "GET LOGICAL DRIVE INFORMATION"); for (Channel = 0; Channel < Enquiry2.ActualChannels; Channel++) - for (TargetID = 0; TargetID < DAC960_MaxTargets; TargetID++) - if (!DAC960_ExecuteType3D(Controller, DAC960_GetDeviceState, - Channel, TargetID, - &Controller->DeviceState[0][Channel][TargetID])) + for (TargetID = 0; TargetID < Enquiry2.MaxTargets; TargetID++) + if (!DAC960_V1_ExecuteType3D(Controller, DAC960_V1_GetDeviceState, + Channel, TargetID, + &Controller->V1.DeviceState + [Channel][TargetID])) return DAC960_Failure(Controller, "GET DEVICE STATE"); /* Initialize the Controller Model Name and Full Model Name fields. */ switch (Enquiry2.HardwareID.SubModel) { - case DAC960_P_PD_PU: - if (Enquiry2.SCSICapability.BusSpeed == DAC960_Ultra) + case DAC960_V1_P_PD_PU: + if (Enquiry2.SCSICapability.BusSpeed == DAC960_V1_Ultra) strcpy(Controller->ModelName, "DAC960PU"); else strcpy(Controller->ModelName, "DAC960PD"); break; - case DAC960_PL: + case DAC960_V1_PL: strcpy(Controller->ModelName, "DAC960PL"); break; - case DAC960_PG: + case DAC960_V1_PG: strcpy(Controller->ModelName, "DAC960PG"); break; - case DAC960_PJ: + case DAC960_V1_PJ: strcpy(Controller->ModelName, "DAC960PJ"); break; - case DAC960_PR: + case DAC960_V1_PR: strcpy(Controller->ModelName, "DAC960PR"); break; - case DAC960_PT: + case DAC960_V1_PT: strcpy(Controller->ModelName, "DAC960PT"); break; - case DAC960_PTL0: + case DAC960_V1_PTL0: strcpy(Controller->ModelName, "DAC960PTL0"); break; - case DAC960_PRL: + case DAC960_V1_PRL: strcpy(Controller->ModelName, "DAC960PRL"); break; - case DAC960_PTL1: + case DAC960_V1_PTL1: strcpy(Controller->ModelName, "DAC960PTL1"); break; - case DAC1164_P: + case DAC960_V1_1164P: strcpy(Controller->ModelName, "DAC1164P"); break; default: @@ -813,61 +1075,197 @@ static boolean DAC960_ReadControllerConfiguration(DAC960_Controller_T return false; } /* - Initialize the Controller Channels, Memory Size, and SAF-TE Enclosure - Management Enabled fields. + Initialize the Controller Channels, Targets, Memory Size, and SAF-TE + Enclosure Management Enabled fields. */ Controller->Channels = Enquiry2.ActualChannels; + Controller->Targets = Enquiry2.MaxTargets; Controller->MemorySize = Enquiry2.MemorySize >> 20; - Controller->SAFTE_EnclosureManagementEnabled = - Enquiry2.FaultManagementType == DAC960_SAFTE; + Controller->V1.SAFTE_EnclosureManagementEnabled = + (Enquiry2.FaultManagementType == DAC960_V1_SAFTE); /* Initialize the Controller Queue Depth, Driver Queue Depth, Logical Drive - Count, Maximum Blocks per Command, and Maximum Scatter/Gather Segments. - The Driver Queue Depth must be at most one less than the Controller Queue - Depth to allow for an automatic drive rebuild operation. + Count, Maximum Blocks per Command, Controller Scatter/Gather Limit, and + Driver Scatter/Gather Limit. The Driver Queue Depth must be at most one + less than the Controller Queue Depth to allow for an automatic drive + rebuild operation. */ - Controller->ControllerQueueDepth = Controller->Enquiry[0].MaxCommands; + Controller->ControllerQueueDepth = Controller->V1.Enquiry.MaxCommands; Controller->DriverQueueDepth = Controller->ControllerQueueDepth - 1; - Controller->LogicalDriveCount = Controller->Enquiry[0].NumberOfLogicalDrives; + if (Controller->DriverQueueDepth > DAC960_MaxDriverQueueDepth) + Controller->DriverQueueDepth = DAC960_MaxDriverQueueDepth; + Controller->LogicalDriveCount = + Controller->V1.Enquiry.NumberOfLogicalDrives; Controller->MaxBlocksPerCommand = Enquiry2.MaxBlocksPerCommand; - Controller->MaxScatterGatherSegments = Enquiry2.MaxScatterGatherEntries; + Controller->ControllerScatterGatherLimit = Enquiry2.MaxScatterGatherEntries; + Controller->DriverScatterGatherLimit = + Controller->ControllerScatterGatherLimit; + if (Controller->DriverScatterGatherLimit > DAC960_V1_ScatterGatherLimit) + Controller->DriverScatterGatherLimit = DAC960_V1_ScatterGatherLimit; /* Initialize the Stripe Size, Segment Size, and Geometry Translation. */ - Controller->StripeSize = Config2.BlocksPerStripe * Config2.BlockFactor - >> (10 - DAC960_BlockSizeBits); - Controller->SegmentSize = Config2.BlocksPerCacheLine * Config2.BlockFactor - >> (10 - DAC960_BlockSizeBits); + Controller->V1.StripeSize = Config2.BlocksPerStripe * Config2.BlockFactor + >> (10 - DAC960_BlockSizeBits); + Controller->V1.SegmentSize = Config2.BlocksPerCacheLine * Config2.BlockFactor + >> (10 - DAC960_BlockSizeBits); switch (Config2.DriveGeometry) { - case DAC960_Geometry_128_32: - Controller->GeometryTranslationHeads = 128; - Controller->GeometryTranslationSectors = 32; + case DAC960_V1_Geometry_128_32: + Controller->V1.GeometryTranslationHeads = 128; + Controller->V1.GeometryTranslationSectors = 32; break; - case DAC960_Geometry_255_63: - Controller->GeometryTranslationHeads = 255; - Controller->GeometryTranslationSectors = 63; + case DAC960_V1_Geometry_255_63: + Controller->V1.GeometryTranslationHeads = 255; + Controller->V1.GeometryTranslationSectors = 63; break; default: return DAC960_Failure(Controller, "CONFIG2 DRIVE GEOMETRY"); } /* - Initialize the Logical Drive Initial State. + Initialize the Logical Drive Initially Accessible flag. */ for (LogicalDriveNumber = 0; LogicalDriveNumber < Controller->LogicalDriveCount; LogicalDriveNumber++) - Controller->LogicalDriveInitialState[LogicalDriveNumber] = - Controller->LogicalDriveInformation[0] - [LogicalDriveNumber].LogicalDriveState; - Controller->LastRebuildStatus = DAC960_NoRebuildOrCheckInProgress; + if (Controller->V1.LogicalDriveInformation + [LogicalDriveNumber].LogicalDriveState != + DAC960_V1_LogicalDrive_Offline) + Controller->LogicalDriveInitiallyAccessible[LogicalDriveNumber] = true; + Controller->V1.LastRebuildStatus = DAC960_V1_NoRebuildOrCheckInProgress; return true; } /* - DAC960_ReportControllerConfiguration reports the Configuration Information of - Controller. + DAC960_V2_ReadControllerConfiguration reads the Configuration Information + from DAC960 V2 Firmware Controllers and initializes the Controller structure. +*/ + +static boolean DAC960_V2_ReadControllerConfiguration(DAC960_Controller_T + *Controller) +{ + DAC960_V2_ControllerInfo_T *ControllerInfo = + &Controller->V2.ControllerInformation; + unsigned short LogicalDeviceNumber = 0; + int ModelNameLength; + if (!DAC960_V2_ControllerInfo(Controller, DAC960_V2_GetControllerInfo, + ControllerInfo, + sizeof(DAC960_V2_ControllerInfo_T))) + return DAC960_Failure(Controller, "GET CONTROLLER INFO"); + if (!DAC960_V2_GeneralInfo(Controller, DAC960_V2_GetHealthStatus, + Controller->V2.HealthStatusBuffer, + sizeof(DAC960_V2_HealthStatusBuffer_T))) + return DAC960_Failure(Controller, "GET HEALTH STATUS"); + /* + Initialize the Controller Model Name and Full Model Name fields. + */ + ModelNameLength = sizeof(ControllerInfo->ControllerName); + if (ModelNameLength > sizeof(Controller->ModelName)-1) + ModelNameLength = sizeof(Controller->ModelName)-1; + memcpy(Controller->ModelName, ControllerInfo->ControllerName, + ModelNameLength); + ModelNameLength--; + while (Controller->ModelName[ModelNameLength] == ' ' || + Controller->ModelName[ModelNameLength] == '\0') + ModelNameLength--; + Controller->ModelName[++ModelNameLength] = '\0'; + strcpy(Controller->FullModelName, "Mylex "); + strcat(Controller->FullModelName, Controller->ModelName); + /* + Initialize the Controller Firmware Version field. + */ + sprintf(Controller->FirmwareVersion, "%d.%02d-%02d", + ControllerInfo->FirmwareMajorVersion, + ControllerInfo->FirmwareMinorVersion, + ControllerInfo->FirmwareTurnNumber); + if (ControllerInfo->FirmwareMajorVersion == 6 && + ControllerInfo->FirmwareMinorVersion == 0 && + ControllerInfo->FirmwareTurnNumber < 1) + { + DAC960_Info("FIRMWARE VERSION %s DOES NOT PROVIDE THE CONTROLLER\n", + Controller, Controller->FirmwareVersion); + DAC960_Info("STATUS MONITORING FUNCTIONALITY NEEDED BY THIS DRIVER.\n", + Controller); + DAC960_Info("PLEASE UPGRADE TO VERSION 6.00-01 OR ABOVE.\n", + Controller); + } + /* + Initialize the Controller Channels, Targets, and Memory Size. + */ + Controller->Channels = ControllerInfo->NumberOfPhysicalChannelsPresent; + Controller->Targets = + ControllerInfo->MaximumTargetsPerChannel + [ControllerInfo->NumberOfPhysicalChannelsPresent-1]; + Controller->MemorySize = ControllerInfo->MemorySizeMB; + /* + Initialize the Controller Queue Depth, Driver Queue Depth, Logical Drive + Count, Maximum Blocks per Command, Controller Scatter/Gather Limit, and + Driver Scatter/Gather Limit. The Driver Queue Depth must be at most one + less than the Controller Queue Depth to allow for an automatic drive + rebuild operation. + */ + Controller->ControllerQueueDepth = ControllerInfo->MaximumParallelCommands; + Controller->DriverQueueDepth = Controller->ControllerQueueDepth - 1; + if (Controller->DriverQueueDepth > DAC960_MaxDriverQueueDepth) + Controller->DriverQueueDepth = DAC960_MaxDriverQueueDepth; + Controller->LogicalDriveCount = ControllerInfo->LogicalDevicesPresent; + Controller->MaxBlocksPerCommand = + ControllerInfo->MaximumDataTransferSizeInBlocks; + Controller->ControllerScatterGatherLimit = + ControllerInfo->MaximumScatterGatherEntries; + Controller->DriverScatterGatherLimit = + Controller->ControllerScatterGatherLimit; + if (Controller->DriverScatterGatherLimit > DAC960_V2_ScatterGatherLimit) + Controller->DriverScatterGatherLimit = DAC960_V2_ScatterGatherLimit; + /* + Initialize the Logical Device Information. + */ + while (true) + { + DAC960_V2_LogicalDeviceInfo_T *NewLogicalDeviceInfo = + &Controller->V2.NewLogicalDeviceInformation; + DAC960_V2_LogicalDeviceInfo_T *LogicalDeviceInfo; + DAC960_V2_PhysicalDevice_T PhysicalDevice; + if (!DAC960_V2_LogicalDeviceInfo(Controller, + DAC960_V2_GetLogicalDeviceInfoValid, + LogicalDeviceNumber, + NewLogicalDeviceInfo, + sizeof(DAC960_V2_LogicalDeviceInfo_T))) + break; + LogicalDeviceNumber = NewLogicalDeviceInfo->LogicalDeviceNumber; + if (LogicalDeviceNumber > DAC960_MaxLogicalDrives) + panic("DAC960: Logical Drive Number %d not supported\n", + LogicalDeviceNumber); + if (NewLogicalDeviceInfo->DeviceBlockSizeInBytes != DAC960_BlockSize) + panic("DAC960: Logical Drive Block Size %d not supported\n", + NewLogicalDeviceInfo->DeviceBlockSizeInBytes); + PhysicalDevice.Controller = 0; + PhysicalDevice.Channel = NewLogicalDeviceInfo->Channel; + PhysicalDevice.TargetID = NewLogicalDeviceInfo->TargetID; + PhysicalDevice.LogicalUnit = NewLogicalDeviceInfo->LogicalUnit; + Controller->V2.LogicalDriveToVirtualDevice[LogicalDeviceNumber] = + PhysicalDevice; + if (NewLogicalDeviceInfo->LogicalDeviceState != + DAC960_V2_LogicalDevice_Offline) + Controller->LogicalDriveInitiallyAccessible[LogicalDeviceNumber] = true; + LogicalDeviceInfo = (DAC960_V2_LogicalDeviceInfo_T *) + kmalloc(sizeof(DAC960_V2_LogicalDeviceInfo_T), GFP_ATOMIC); + if (LogicalDeviceInfo == NULL) + return DAC960_Failure(Controller, "LOGICAL DEVICE ALLOCATION"); + Controller->V2.LogicalDeviceInformation[LogicalDeviceNumber] = + LogicalDeviceInfo; + memcpy(LogicalDeviceInfo, NewLogicalDeviceInfo, + sizeof(DAC960_V2_LogicalDeviceInfo_T)); + LogicalDeviceNumber++; + } + return true; +} + + +/* + DAC960_ReportControllerConfiguration reports the Configuration Information + for Controller. */ static boolean DAC960_ReportControllerConfiguration(DAC960_Controller_T @@ -893,54 +1291,60 @@ static boolean DAC960_ReportControllerConfiguration(DAC960_Controller_T Controller, Controller->ControllerQueueDepth, Controller->MaxBlocksPerCommand); DAC960_Info(" Driver Queue Depth: %d, " - "Maximum Scatter/Gather Segments: %d\n", + "Scatter/Gather Limit: %d of %d Segments\n", Controller, Controller->DriverQueueDepth, - Controller->MaxScatterGatherSegments); - DAC960_Info(" Stripe Size: %dKB, Segment Size: %dKB, " - "BIOS Geometry: %d/%d\n", Controller, - Controller->StripeSize, - Controller->SegmentSize, - Controller->GeometryTranslationHeads, - Controller->GeometryTranslationSectors); - if (Controller->SAFTE_EnclosureManagementEnabled) - DAC960_Info(" SAF-TE Enclosure Management Enabled\n", Controller); + Controller->DriverScatterGatherLimit, + Controller->ControllerScatterGatherLimit); + if (Controller->FirmwareType == DAC960_V1_Controller) + { + DAC960_Info(" Stripe Size: %dKB, Segment Size: %dKB, " + "BIOS Geometry: %d/%d\n", Controller, + Controller->V1.StripeSize, + Controller->V1.SegmentSize, + Controller->V1.GeometryTranslationHeads, + Controller->V1.GeometryTranslationSectors); + if (Controller->V1.SAFTE_EnclosureManagementEnabled) + DAC960_Info(" SAF-TE Enclosure Management Enabled\n", Controller); + } return true; } /* - DAC960_ReadDeviceConfiguration reads the Device Configuration Information by - requesting the SCSI Inquiry and SCSI Inquiry Unit Serial Number information - for each device connected to Controller. + DAC960_V1_ReadDeviceConfiguration reads the Device Configuration Information + for DAC960 V1 Firmware Controllers by requesting the SCSI Inquiry and SCSI + Inquiry Unit Serial Number information for each device connected to + Controller. */ -static boolean DAC960_ReadDeviceConfiguration(DAC960_Controller_T *Controller) +static boolean DAC960_V1_ReadDeviceConfiguration(DAC960_Controller_T + *Controller) { - DAC960_DCDB_T DCDBs[DAC960_MaxChannels], *DCDB; - Semaphore_T Semaphores[DAC960_MaxChannels], *Semaphore; + DAC960_V1_DCDB_T DCDBs[DAC960_V1_MaxChannels], *DCDB; + Semaphore_T Semaphores[DAC960_V1_MaxChannels], *Semaphore; unsigned long ProcessorFlags; int Channel, TargetID; - for (TargetID = 0; TargetID < DAC960_MaxTargets; TargetID++) + for (TargetID = 0; TargetID < Controller->Targets; TargetID++) { for (Channel = 0; Channel < Controller->Channels; Channel++) { - DAC960_Command_T *Command = &Controller->Commands[Channel]; + DAC960_Command_T *Command = Controller->Commands[Channel]; DAC960_SCSI_Inquiry_T *InquiryStandardData = - &Controller->InquiryStandardData[Channel][TargetID]; + &Controller->V1.InquiryStandardData[Channel][TargetID]; InquiryStandardData->PeripheralDeviceType = 0x1F; Semaphore = &Semaphores[Channel]; init_MUTEX_LOCKED(Semaphore); DCDB = &DCDBs[Channel]; - DAC960_ClearCommand(Command); + DAC960_V1_ClearCommand(Command); Command->CommandType = DAC960_ImmediateCommand; Command->Semaphore = Semaphore; - Command->CommandMailbox.Type3.CommandOpcode = DAC960_DCDB; - Command->CommandMailbox.Type3.BusAddress = Virtual_to_Bus(DCDB); + Command->V1.CommandMailbox.Type3.CommandOpcode = DAC960_V1_DCDB; + Command->V1.CommandMailbox.Type3.BusAddress = Virtual_to_Bus(DCDB); DCDB->Channel = Channel; DCDB->TargetID = TargetID; - DCDB->Direction = DAC960_DCDB_DataTransferDeviceToSystem; + DCDB->Direction = DAC960_V1_DCDB_DataTransferDeviceToSystem; DCDB->EarlyStatus = false; - DCDB->Timeout = DAC960_DCDB_Timeout_10_seconds; + DCDB->Timeout = DAC960_V1_DCDB_Timeout_10_seconds; DCDB->NoAutomaticRequestSense = false; DCDB->DisconnectPermitted = true; DCDB->TransferLength = sizeof(DAC960_SCSI_Inquiry_T); @@ -960,13 +1364,14 @@ static boolean DAC960_ReadDeviceConfiguration(DAC960_Controller_T *Controller) } for (Channel = 0; Channel < Controller->Channels; Channel++) { - DAC960_Command_T *Command = &Controller->Commands[Channel]; + DAC960_Command_T *Command = Controller->Commands[Channel]; DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber = - &Controller->InquiryUnitSerialNumber[Channel][TargetID]; + &Controller->V1.InquiryUnitSerialNumber[Channel][TargetID]; InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F; Semaphore = &Semaphores[Channel]; down(Semaphore); - if (Command->CommandStatus != DAC960_NormalCompletion) continue; + if (Command->V1.CommandStatus != DAC960_V1_NormalCompletion) + continue; Command->Semaphore = Semaphore; DCDB = &DCDBs[Channel]; DCDB->TransferLength = sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); @@ -984,107 +1389,215 @@ static boolean DAC960_ReadDeviceConfiguration(DAC960_Controller_T *Controller) down(Semaphore); } } - return true; + return true; +} + + +/* + DAC960_V2_ReadDeviceConfiguration reads the Device Configuration Information + for DAC960 V2 Firmware Controllers by requesting the Physical Device + Information and SCSI Inquiry Unit Serial Number information for each + device connected to Controller. +*/ + +static boolean DAC960_V2_ReadDeviceConfiguration(DAC960_Controller_T + *Controller) +{ + unsigned char Channel = 0, TargetID = 0, LogicalUnit = 0; + unsigned short PhysicalDeviceIndex = 0; + while (true) + { + DAC960_V2_PhysicalDeviceInfo_T *NewPhysicalDeviceInfo = + &Controller->V2.NewPhysicalDeviceInformation; + DAC960_V2_PhysicalDeviceInfo_T *PhysicalDeviceInfo; + DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber; + DAC960_Command_T *Command; + DAC960_V2_CommandMailbox_T *CommandMailbox; + if (!DAC960_V2_PhysicalDeviceInfo(Controller, + DAC960_V2_GetPhysicalDeviceInfoValid, + Channel, + TargetID, + LogicalUnit, + NewPhysicalDeviceInfo, + sizeof(DAC960_V2_PhysicalDeviceInfo_T))) + break; + Channel = NewPhysicalDeviceInfo->Channel; + TargetID = NewPhysicalDeviceInfo->TargetID; + LogicalUnit = NewPhysicalDeviceInfo->LogicalUnit; + PhysicalDeviceInfo = (DAC960_V2_PhysicalDeviceInfo_T *) + kmalloc(sizeof(DAC960_V2_PhysicalDeviceInfo_T), GFP_ATOMIC); + if (PhysicalDeviceInfo == NULL) + return DAC960_Failure(Controller, "PHYSICAL DEVICE ALLOCATION"); + Controller->V2.PhysicalDeviceInformation[PhysicalDeviceIndex] = + PhysicalDeviceInfo; + memcpy(PhysicalDeviceInfo, NewPhysicalDeviceInfo, + sizeof(DAC960_V2_PhysicalDeviceInfo_T)); + InquiryUnitSerialNumber = (DAC960_SCSI_Inquiry_UnitSerialNumber_T *) + kmalloc(sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T), GFP_ATOMIC); + if (InquiryUnitSerialNumber == NULL) + return DAC960_Failure(Controller, "SERIAL NUMBER ALLOCATION"); + Controller->V2.InquiryUnitSerialNumber[PhysicalDeviceIndex] = + InquiryUnitSerialNumber; + memset(InquiryUnitSerialNumber, 0, + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T)); + InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F; + Command = DAC960_AllocateCommand(Controller); + CommandMailbox = &Command->V2.CommandMailbox; + DAC960_V2_ClearCommand(Command); + Command->CommandType = DAC960_ImmediateCommand; + CommandMailbox->SCSI_10.CommandOpcode = DAC960_V2_SCSI_10_Passthru; + CommandMailbox->SCSI_10.CommandControlBits + .DataTransferControllerToHost = true; + CommandMailbox->SCSI_10.CommandControlBits + .NoAutoRequestSense = true; + CommandMailbox->SCSI_10.DataTransferSize = + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); + CommandMailbox->SCSI_10.PhysicalDevice.LogicalUnit = LogicalUnit; + CommandMailbox->SCSI_10.PhysicalDevice.TargetID = TargetID; + CommandMailbox->SCSI_10.PhysicalDevice.Channel = Channel; + CommandMailbox->SCSI_10.CDBLength = 6; + CommandMailbox->SCSI_10.SCSI_CDB[0] = 0x12; /* INQUIRY */ + CommandMailbox->SCSI_10.SCSI_CDB[1] = 1; /* EVPD = 1 */ + CommandMailbox->SCSI_10.SCSI_CDB[2] = 0x80; /* Page Code */ + CommandMailbox->SCSI_10.SCSI_CDB[3] = 0; /* Reserved */ + CommandMailbox->SCSI_10.SCSI_CDB[4] = + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); + CommandMailbox->SCSI_10.SCSI_CDB[5] = 0; /* Control */ + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Virtual_to_Bus(InquiryUnitSerialNumber); + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->SCSI_10.DataTransferSize; + DAC960_ExecuteCommand(Command); + DAC960_DeallocateCommand(Command); + PhysicalDeviceIndex++; + LogicalUnit++; + } + return true; +} + + +/* + DAC960_SanitizeInquiryData sanitizes the Vendor, Model, Revision, and + Product Serial Number fields of the Inquiry Standard Data and Inquiry + Unit Serial Number structures. +*/ + +static void DAC960_SanitizeInquiryData(DAC960_SCSI_Inquiry_T + *InquiryStandardData, + DAC960_SCSI_Inquiry_UnitSerialNumber_T + *InquiryUnitSerialNumber, + unsigned char *Vendor, + unsigned char *Model, + unsigned char *Revision, + unsigned char *SerialNumber) +{ + int SerialNumberLength, i; + if (InquiryStandardData->PeripheralDeviceType == 0x1F) return; + for (i = 0; i < sizeof(InquiryStandardData->VendorIdentification); i++) + { + unsigned char VendorCharacter = + InquiryStandardData->VendorIdentification[i]; + Vendor[i] = (VendorCharacter >= ' ' && VendorCharacter <= '~' + ? VendorCharacter : ' '); + } + Vendor[sizeof(InquiryStandardData->VendorIdentification)] = '\0'; + for (i = 0; i < sizeof(InquiryStandardData->ProductIdentification); i++) + { + unsigned char ModelCharacter = + InquiryStandardData->ProductIdentification[i]; + Model[i] = (ModelCharacter >= ' ' && ModelCharacter <= '~' + ? ModelCharacter : ' '); + } + Model[sizeof(InquiryStandardData->ProductIdentification)] = '\0'; + for (i = 0; i < sizeof(InquiryStandardData->ProductRevisionLevel); i++) + { + unsigned char RevisionCharacter = + InquiryStandardData->ProductRevisionLevel[i]; + Revision[i] = (RevisionCharacter >= ' ' && RevisionCharacter <= '~' + ? RevisionCharacter : ' '); + } + Revision[sizeof(InquiryStandardData->ProductRevisionLevel)] = '\0'; + if (InquiryUnitSerialNumber->PeripheralDeviceType == 0x1F) return; + SerialNumberLength = InquiryUnitSerialNumber->PageLength; + if (SerialNumberLength > + sizeof(InquiryUnitSerialNumber->ProductSerialNumber)) + SerialNumberLength = sizeof(InquiryUnitSerialNumber->ProductSerialNumber); + for (i = 0; i < SerialNumberLength; i++) + { + unsigned char SerialNumberCharacter = + InquiryUnitSerialNumber->ProductSerialNumber[i]; + SerialNumber[i] = + (SerialNumberCharacter >= ' ' && SerialNumberCharacter <= '~' + ? SerialNumberCharacter : ' '); + } + SerialNumber[SerialNumberLength] = '\0'; } /* - DAC960_ReportDeviceConfiguration reports the Device Configuration Information - of Controller. + DAC960_V1_ReportDeviceConfiguration reports the Device Configuration + Information for DAC960 V1 Firmware Controllers. */ -static boolean DAC960_ReportDeviceConfiguration(DAC960_Controller_T *Controller) +static boolean DAC960_V1_ReportDeviceConfiguration(DAC960_Controller_T + *Controller) { int LogicalDriveNumber, Channel, TargetID; DAC960_Info(" Physical Devices:\n", Controller); for (Channel = 0; Channel < Controller->Channels; Channel++) - for (TargetID = 0; TargetID < DAC960_MaxTargets; TargetID++) + for (TargetID = 0; TargetID < Controller->Targets; TargetID++) { DAC960_SCSI_Inquiry_T *InquiryStandardData = - &Controller->InquiryStandardData[Channel][TargetID]; + &Controller->V1.InquiryStandardData[Channel][TargetID]; DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber = - &Controller->InquiryUnitSerialNumber[Channel][TargetID]; - DAC960_DeviceState_T *DeviceState = - &Controller->DeviceState[Controller->DeviceStateIndex] - [Channel][TargetID]; - DAC960_ErrorTable_T *ErrorTable = - &Controller->ErrorTable[Controller->ErrorTableIndex]; - DAC960_ErrorTableEntry_T *ErrorEntry = - &ErrorTable->ErrorTableEntries[Channel][TargetID]; + &Controller->V1.InquiryUnitSerialNumber[Channel][TargetID]; + DAC960_V1_DeviceState_T *DeviceState = + &Controller->V1.DeviceState[Channel][TargetID]; + DAC960_V1_ErrorTableEntry_T *ErrorEntry = + &Controller->V1.ErrorTable.ErrorTableEntries[Channel][TargetID]; char Vendor[1+sizeof(InquiryStandardData->VendorIdentification)]; char Model[1+sizeof(InquiryStandardData->ProductIdentification)]; char Revision[1+sizeof(InquiryStandardData->ProductRevisionLevel)]; char SerialNumber[1+sizeof(InquiryUnitSerialNumber ->ProductSerialNumber)]; - int i; if (InquiryStandardData->PeripheralDeviceType == 0x1F) continue; - for (i = 0; i < sizeof(Vendor)-1; i++) - { - unsigned char VendorCharacter = - InquiryStandardData->VendorIdentification[i]; - Vendor[i] = (VendorCharacter >= ' ' && VendorCharacter <= '~' - ? VendorCharacter : ' '); - } - Vendor[sizeof(Vendor)-1] = '\0'; - for (i = 0; i < sizeof(Model)-1; i++) - { - unsigned char ModelCharacter = - InquiryStandardData->ProductIdentification[i]; - Model[i] = (ModelCharacter >= ' ' && ModelCharacter <= '~' - ? ModelCharacter : ' '); - } - Model[sizeof(Model)-1] = '\0'; - for (i = 0; i < sizeof(Revision)-1; i++) - { - unsigned char RevisionCharacter = - InquiryStandardData->ProductRevisionLevel[i]; - Revision[i] = (RevisionCharacter >= ' ' && RevisionCharacter <= '~' - ? RevisionCharacter : ' '); - } - Revision[sizeof(Revision)-1] = '\0'; + DAC960_SanitizeInquiryData(InquiryStandardData, InquiryUnitSerialNumber, + Vendor, Model, Revision, SerialNumber); DAC960_Info(" %d:%d%s Vendor: %s Model: %s Revision: %s\n", Controller, Channel, TargetID, (TargetID < 10 ? " " : ""), Vendor, Model, Revision); if (InquiryUnitSerialNumber->PeripheralDeviceType != 0x1F) + DAC960_Info(" Serial Number: %s\n", Controller, SerialNumber); + if (DeviceState->Present && + DeviceState->DeviceType == DAC960_V1_DiskType) { - int SerialNumberLength = InquiryUnitSerialNumber->PageLength; - if (SerialNumberLength > - sizeof(InquiryUnitSerialNumber->ProductSerialNumber)) - SerialNumberLength = - sizeof(InquiryUnitSerialNumber->ProductSerialNumber); - for (i = 0; i < SerialNumberLength; i++) - { - unsigned char SerialNumberCharacter = - InquiryUnitSerialNumber->ProductSerialNumber[i]; - SerialNumber[i] = - (SerialNumberCharacter >= ' ' && SerialNumberCharacter <= '~' - ? SerialNumberCharacter : ' '); - } - SerialNumber[SerialNumberLength] = '\0'; - DAC960_Info(" Serial Number: %s\n", - Controller, SerialNumber); - } - if (DeviceState->Present && DeviceState->DeviceType == DAC960_DiskType) - { - if (Controller->DeviceResetCount[Channel][TargetID] > 0) + if (Controller->V1.DeviceResetCount[Channel][TargetID] > 0) DAC960_Info(" Disk Status: %s, %d blocks, %d resets\n", Controller, - (DeviceState->DeviceState == DAC960_Device_Dead + (DeviceState->DeviceState == DAC960_V1_Device_Dead ? "Dead" - : DeviceState->DeviceState == DAC960_Device_WriteOnly - ? "Write-Only" - : DeviceState->DeviceState == DAC960_Device_Online - ? "Online" : "Standby"), + : DeviceState->DeviceState + == DAC960_V1_Device_WriteOnly + ? "Write-Only" + : DeviceState->DeviceState + == DAC960_V1_Device_Online + ? "Online" : "Standby"), DeviceState->DiskSize, - Controller->DeviceResetCount[Channel][TargetID]); + Controller->V1.DeviceResetCount[Channel][TargetID]); else DAC960_Info(" Disk Status: %s, %d blocks\n", Controller, - (DeviceState->DeviceState == DAC960_Device_Dead + (DeviceState->DeviceState == DAC960_V1_Device_Dead ? "Dead" - : DeviceState->DeviceState == DAC960_Device_WriteOnly - ? "Write-Only" - : DeviceState->DeviceState == DAC960_Device_Online - ? "Online" : "Standby"), + : DeviceState->DeviceState + == DAC960_V1_Device_WriteOnly + ? "Write-Only" + : DeviceState->DeviceState + == DAC960_V1_Device_Online + ? "Online" : "Standby"), DeviceState->DiskSize); } if (ErrorEntry->ParityErrorCount > 0 || @@ -1103,17 +1616,16 @@ static boolean DAC960_ReportDeviceConfiguration(DAC960_Controller_T *Controller) LogicalDriveNumber < Controller->LogicalDriveCount; LogicalDriveNumber++) { - DAC960_LogicalDriveInformation_T *LogicalDriveInformation = - &Controller->LogicalDriveInformation - [Controller->LogicalDriveInformationIndex][LogicalDriveNumber]; + DAC960_V1_LogicalDriveInformation_T *LogicalDriveInformation = + &Controller->V1.LogicalDriveInformation[LogicalDriveNumber]; DAC960_Info(" /dev/rd/c%dd%d: RAID-%d, %s, %d blocks, %s\n", Controller, Controller->ControllerNumber, LogicalDriveNumber, LogicalDriveInformation->RAIDLevel, - (LogicalDriveInformation->LogicalDriveState == - DAC960_LogicalDrive_Online + (LogicalDriveInformation->LogicalDriveState + == DAC960_V1_LogicalDrive_Online ? "Online" - : LogicalDriveInformation->LogicalDriveState == - DAC960_LogicalDrive_Critical + : LogicalDriveInformation->LogicalDriveState + == DAC960_V1_LogicalDrive_Critical ? "Critical" : "Offline"), LogicalDriveInformation->LogicalDriveSize, (LogicalDriveInformation->WriteBack @@ -1123,69 +1635,256 @@ static boolean DAC960_ReportDeviceConfiguration(DAC960_Controller_T *Controller) } -static inline int DAC_new_segment(request_queue_t *q, struct request *req, - int __max_segments) -{ - int max_segments; - DAC960_Controller_T * Controller = q->queuedata; - - max_segments = Controller->MaxSegmentsPerRequest[MINOR(req->rq_dev)]; - if (__max_segments < max_segments) - max_segments = __max_segments; +/* + DAC960_V2_ReportDeviceConfiguration reports the Device Configuration + Information for DAC960 V2 Firmware Controllers. +*/ - if (req->nr_segments < max_segments) { - req->nr_segments++; - q->elevator.nr_segments++; - return 1; +static boolean DAC960_V2_ReportDeviceConfiguration(DAC960_Controller_T + *Controller) +{ + int PhysicalDeviceIndex, LogicalDriveNumber; + DAC960_Info(" Physical Devices:\n", Controller); + for (PhysicalDeviceIndex = 0; + PhysicalDeviceIndex < DAC960_V2_MaxPhysicalDevices; + PhysicalDeviceIndex++) + { + DAC960_V2_PhysicalDeviceInfo_T *PhysicalDeviceInfo = + Controller->V2.PhysicalDeviceInformation[PhysicalDeviceIndex]; + DAC960_SCSI_Inquiry_T *InquiryStandardData = + (DAC960_SCSI_Inquiry_T *) &PhysicalDeviceInfo->SCSI_InquiryData; + DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber = + Controller->V2.InquiryUnitSerialNumber[PhysicalDeviceIndex]; + char Vendor[1+sizeof(InquiryStandardData->VendorIdentification)]; + char Model[1+sizeof(InquiryStandardData->ProductIdentification)]; + char Revision[1+sizeof(InquiryStandardData->ProductRevisionLevel)]; + char SerialNumber[1+sizeof(InquiryUnitSerialNumber->ProductSerialNumber)]; + if (PhysicalDeviceInfo == NULL) break; + DAC960_SanitizeInquiryData(InquiryStandardData, InquiryUnitSerialNumber, + Vendor, Model, Revision, SerialNumber); + DAC960_Info(" %d:%d%s Vendor: %s Model: %s Revision: %s\n", + Controller, + PhysicalDeviceInfo->Channel, + PhysicalDeviceInfo->TargetID, + (PhysicalDeviceInfo->TargetID < 10 ? " " : ""), + Vendor, Model, Revision); + if (PhysicalDeviceInfo->NegotiatedSynchronousMegaTransfers == 0) + DAC960_Info(" %sAsynchronous\n", Controller, + (PhysicalDeviceInfo->NegotiatedDataWidthBits == 16 + ? "Wide " :"")); + else + DAC960_Info(" %sSynchronous at %d MB/sec\n", Controller, + (PhysicalDeviceInfo->NegotiatedDataWidthBits == 16 + ? "Wide " :""), + (PhysicalDeviceInfo->NegotiatedSynchronousMegaTransfers + * (PhysicalDeviceInfo->NegotiatedDataWidthBits == 16 + ? 2 : 1))); + if (InquiryUnitSerialNumber->PeripheralDeviceType != 0x1F) + DAC960_Info(" Serial Number: %s\n", Controller, SerialNumber); + if (PhysicalDeviceInfo->PhysicalDeviceState == + DAC960_V2_Device_Unconfigured) + continue; + DAC960_Info(" Disk Status: %s, %d blocks\n", Controller, + (PhysicalDeviceInfo->PhysicalDeviceState + == DAC960_V2_Device_Online + ? "Online" + : PhysicalDeviceInfo->PhysicalDeviceState + == DAC960_V2_Device_WriteOnly + ? "Write-Only" + : PhysicalDeviceInfo->PhysicalDeviceState + == DAC960_V2_Device_Dead + ? "Dead" : "Standby"), + PhysicalDeviceInfo + ->ConfigurableDeviceSizeIn512ByteBlocksOrMB); + if (PhysicalDeviceInfo->ParityErrors == 0 && + PhysicalDeviceInfo->SoftErrors == 0 && + PhysicalDeviceInfo->HardErrors == 0 && + PhysicalDeviceInfo->MiscellaneousErrors == 0 && + PhysicalDeviceInfo->CommandTimeouts == 0 && + PhysicalDeviceInfo->Retries == 0 && + PhysicalDeviceInfo->Aborts == 0 && + PhysicalDeviceInfo->PredictedFailuresDetected == 0) + continue; + DAC960_Info(" Errors - Parity: %d, Soft: %d, " + "Hard: %d, Misc: %d\n", Controller, + PhysicalDeviceInfo->ParityErrors, + PhysicalDeviceInfo->SoftErrors, + PhysicalDeviceInfo->HardErrors, + PhysicalDeviceInfo->MiscellaneousErrors); + DAC960_Info(" Timeouts: %d, Retries: %d, " + "Aborts: %d, Predicted: %d\n", Controller, + PhysicalDeviceInfo->CommandTimeouts, + PhysicalDeviceInfo->Retries, + PhysicalDeviceInfo->Aborts, + PhysicalDeviceInfo->PredictedFailuresDetected); + } + DAC960_Info(" Logical Drives:\n", Controller); + for (LogicalDriveNumber = 0; + LogicalDriveNumber < DAC960_MaxLogicalDrives; + LogicalDriveNumber++) + { + DAC960_V2_LogicalDeviceInfo_T *LogicalDeviceInfo = + Controller->V2.LogicalDeviceInformation[LogicalDriveNumber]; + unsigned char *ReadCacheStatus[] = { "Read Cache Disabled", + "Read Cache Enabled", + "Read Ahead Enabled", + "Intelligent Read Ahead Enabled", + "-", "-", "-", "-" }; + unsigned char *WriteCacheStatus[] = { "Write Cache Disabled", + "Logical Device Read Only", + "Write Cache Enabled", + "Intelligent Write Cache Enabled", + "-", "-", "-", "-" }; + unsigned char *GeometryTranslation; + if (LogicalDeviceInfo == NULL) continue; + switch(LogicalDeviceInfo->DriveGeometry) + { + case DAC960_V2_Geometry_128_32: + GeometryTranslation = "128/32"; + break; + case DAC960_V2_Geometry_255_63: + GeometryTranslation = "255/63"; + break; + default: + GeometryTranslation = "Invalid"; + DAC960_Error("Illegal Logical Device Geometry %d\n", + Controller, LogicalDeviceInfo->DriveGeometry); + break; } - return 0; -} + DAC960_Info(" /dev/rd/c%dd%d: RAID-%d, %s, %d blocks\n", + Controller, Controller->ControllerNumber, LogicalDriveNumber, + LogicalDeviceInfo->RAIDLevel, + (LogicalDeviceInfo->LogicalDeviceState + == DAC960_V2_LogicalDevice_Online + ? "Online" + : LogicalDeviceInfo->LogicalDeviceState + == DAC960_V2_LogicalDevice_Critical + ? "Critical" : "Offline"), + LogicalDeviceInfo->ConfigurableDeviceSizeIn512ByteBlocksOrMB); + DAC960_Info(" Logical Device %s, BIOS Geometry: %s\n", + Controller, + (LogicalDeviceInfo->LogicalDeviceControl + .LogicalDeviceInitialized + ? "Initialized" : "Uninitialized"), + GeometryTranslation); + if (LogicalDeviceInfo->StripeSize == 0) + { + if (LogicalDeviceInfo->CacheLineSize == 0) + DAC960_Info(" Stripe Size: N/A, " + "Segment Size: N/A\n", Controller); + else + DAC960_Info(" Stripe Size: N/A, " + "Segment Size: %dKB\n", Controller, + 1 << (LogicalDeviceInfo->CacheLineSize - 2)); + } + else + { + if (LogicalDeviceInfo->CacheLineSize == 0) + DAC960_Info(" Stripe Size: %dKB, " + "Segment Size: N/A\n", Controller, + 1 << (LogicalDeviceInfo->StripeSize - 2)); + else + DAC960_Info(" Stripe Size: %dKB, " + "Segment Size: %dKB\n", Controller, + 1 << (LogicalDeviceInfo->StripeSize - 2), + 1 << (LogicalDeviceInfo->CacheLineSize - 2)); + } + DAC960_Info(" %s, %s\n", Controller, + ReadCacheStatus[ + LogicalDeviceInfo->LogicalDeviceControl.ReadCache], + WriteCacheStatus[ + LogicalDeviceInfo->LogicalDeviceControl.WriteCache]); + if (LogicalDeviceInfo->SoftErrors > 0 || + LogicalDeviceInfo->CommandsFailed > 0 || + LogicalDeviceInfo->DeferredWriteErrors) + DAC960_Info(" Errors - Soft: %d, Failed: %d, " + "Deferred Write: %d\n", Controller, + LogicalDeviceInfo->SoftErrors, + LogicalDeviceInfo->CommandsFailed, + LogicalDeviceInfo->DeferredWriteErrors); -static int DAC_back_merge_fn(request_queue_t *q, struct request *req, - struct buffer_head *bh, int __max_segments) -{ - if (req->bhtail->b_data + req->bhtail->b_size == bh->b_data) - return 1; - return DAC_new_segment(q, req, __max_segments); + } + return true; } -static int DAC_front_merge_fn(request_queue_t *q, struct request *req, - struct buffer_head *bh, int __max_segments) + +/* + DAC960_BackMergeFunction is the Back Merge Function for the DAC960 driver. +*/ + +static int DAC960_BackMergeFunction(RequestQueue_T *RequestQueue, + IO_Request_T *Request, + BufferHeader_T *BufferHeader, + int MaxSegments) { - if (bh->b_data + bh->b_size == req->bh->b_data) - return 1; - return DAC_new_segment(q, req, __max_segments); + DAC960_Controller_T *Controller = + (DAC960_Controller_T *) RequestQueue->queuedata; + if (Request->bhtail->b_data + Request->bhtail->b_size == BufferHeader->b_data) + return true; + if (Request->nr_segments < MaxSegments && + Request->nr_segments < Controller->DriverScatterGatherLimit) + { + Request->nr_segments++; + RequestQueue->elevator.nr_segments++; + return true; + } + return false; } -static int DAC_merge_requests_fn(request_queue_t *q, - struct request *req, - struct request *next, - int __max_segments) + +/* + DAC960_FrontMergeFunction is the Front Merge Function for the DAC960 driver. +*/ + +static int DAC960_FrontMergeFunction(RequestQueue_T *RequestQueue, + IO_Request_T *Request, + BufferHeader_T *BufferHeader, + int MaxSegments) { - int max_segments; - DAC960_Controller_T * Controller = q->queuedata; - int total_segments = req->nr_segments + next->nr_segments; - int same_segment; + DAC960_Controller_T *Controller = + (DAC960_Controller_T *) RequestQueue->queuedata; + if (BufferHeader->b_data + BufferHeader->b_size == Request->bh->b_data) + return true; + if (Request->nr_segments < MaxSegments && + Request->nr_segments < Controller->DriverScatterGatherLimit) + { + Request->nr_segments++; + RequestQueue->elevator.nr_segments++; + return true; + } + return false; +} - max_segments = Controller->MaxSegmentsPerRequest[MINOR(req->rq_dev)]; - if (__max_segments < max_segments) - max_segments = __max_segments; - same_segment = 0; - if (req->bhtail->b_data + req->bhtail->b_size == next->bh->b_data) - { - total_segments--; - same_segment = 1; - } - - if (total_segments > max_segments) - return 0; +/* + DAC960_MergeRequestsFunction is the Merge Requests Function for the + DAC960 driver. +*/ - q->elevator.nr_segments -= same_segment; - req->nr_segments = total_segments; - return 1; +static int DAC960_MergeRequestsFunction(RequestQueue_T *RequestQueue, + IO_Request_T *Request, + IO_Request_T *NextRequest, + int MaxSegments) +{ + DAC960_Controller_T *Controller = + (DAC960_Controller_T *) RequestQueue->queuedata; + int TotalSegments = Request->nr_segments + NextRequest->nr_segments; + int SameSegment = 0; + if (Request->bhtail->b_data + Request->bhtail->b_size + == NextRequest->bh->b_data) + { + TotalSegments--; + SameSegment = 1; + } + if (TotalSegments > MaxSegments || + TotalSegments > Controller->DriverScatterGatherLimit) + return false; + RequestQueue->elevator.nr_segments -= SameSegment; + Request->nr_segments = TotalSegments; + return true; } + /* DAC960_RegisterBlockDevice registers the Block Device structures associated with Controller. @@ -1193,47 +1892,40 @@ static int DAC_merge_requests_fn(request_queue_t *q, static boolean DAC960_RegisterBlockDevice(DAC960_Controller_T *Controller) { - request_queue_t * q; - - static void (*RequestFunctions[DAC960_MaxControllers])(request_queue_t *) = - { DAC960_RequestFunction0, DAC960_RequestFunction1, - DAC960_RequestFunction2, DAC960_RequestFunction3, - DAC960_RequestFunction4, DAC960_RequestFunction5, - DAC960_RequestFunction6, DAC960_RequestFunction7 }; int MajorNumber = DAC960_MAJOR + Controller->ControllerNumber; GenericDiskInfo_T *GenericDiskInfo; + RequestQueue_T *RequestQueue; int MinorNumber; /* Register the Block Device Major Number for this DAC960 Controller. */ - if (devfs_register_blkdev(MajorNumber, "dac960", &DAC960_FileOperations) < 0) + if (devfs_register_blkdev(MajorNumber, "dac960", + &DAC960_BlockDeviceOperations) < 0) { DAC960_Error("UNABLE TO ACQUIRE MAJOR NUMBER %d - DETACHING\n", Controller, MajorNumber); return false; } /* - Initialize the I/O Request Function. + Initialize the I/O Request Queue. */ - q = BLK_DEFAULT_QUEUE(MajorNumber); - blk_init_queue(q, RequestFunctions[Controller->ControllerNumber]); - blk_queue_headactive(q, 0); - q->back_merge_fn = DAC_back_merge_fn; - q->front_merge_fn = DAC_front_merge_fn; - q->merge_requests_fn = DAC_merge_requests_fn; - q->queuedata = (void *) Controller; - + RequestQueue = BLK_DEFAULT_QUEUE(MajorNumber); + blk_init_queue(RequestQueue, DAC960_RequestFunction); + blk_queue_headactive(RequestQueue, 0); + RequestQueue->back_merge_fn = DAC960_BackMergeFunction; + RequestQueue->front_merge_fn = DAC960_FrontMergeFunction; + RequestQueue->merge_requests_fn = DAC960_MergeRequestsFunction; + RequestQueue->queuedata = Controller; + Controller->RequestQueue = RequestQueue; /* Initialize the Disk Partitions array, Partition Sizes array, Block Sizes - array, Max Sectors per Request array, and Max Segments per Request array. + array, and Max Sectors per Request array. */ for (MinorNumber = 0; MinorNumber < DAC960_MinorCount; MinorNumber++) { Controller->BlockSizes[MinorNumber] = BLOCK_SIZE; Controller->MaxSectorsPerRequest[MinorNumber] = Controller->MaxBlocksPerCommand; - Controller->MaxSegmentsPerRequest[MinorNumber] = - Controller->MaxScatterGatherSegments; } Controller->GenericDiskInfo.part = Controller->DiskPartitions; Controller->GenericDiskInfo.sizes = Controller->PartitionSizes; @@ -1247,13 +1939,12 @@ static boolean DAC960_RegisterBlockDevice(DAC960_Controller_T *Controller) Complete initialization of the Generic Disk Information structure. */ Controller->GenericDiskInfo.major = MajorNumber; - Controller->GenericDiskInfo.major_name = "dac960"; + Controller->GenericDiskInfo.major_name = "rd"; Controller->GenericDiskInfo.minor_shift = DAC960_MaxPartitionsBits; Controller->GenericDiskInfo.max_p = DAC960_MaxPartitions; Controller->GenericDiskInfo.nr_real = Controller->LogicalDriveCount; - Controller->GenericDiskInfo.real_devices = Controller; Controller->GenericDiskInfo.next = NULL; - Controller->GenericDiskInfo.fops = &DAC960_FileOperations; + Controller->GenericDiskInfo.fops = &DAC960_BlockDeviceOperations; /* Install the Generic Disk Information structure at the end of the list. */ @@ -1284,7 +1975,7 @@ static void DAC960_UnregisterBlockDevice(DAC960_Controller_T *Controller) */ devfs_unregister_blkdev(MajorNumber, "dac960"); /* - Remove the I/O Request Function. + Remove the I/O Request Queue. */ blk_cleanup_queue(BLK_DEFAULT_QUEUE(MajorNumber)); /* @@ -1313,6 +2004,463 @@ static void DAC960_UnregisterBlockDevice(DAC960_Controller_T *Controller) /* + DAC960_RegisterDisk registers the DAC960 Logical Disk Device for Logical + Drive Number if it exists. +*/ + +static void DAC960_RegisterDisk(DAC960_Controller_T *Controller, + int LogicalDriveNumber) +{ + if (Controller->FirmwareType == DAC960_V1_Controller) + { + if (LogicalDriveNumber > Controller->LogicalDriveCount - 1) return; + register_disk(&Controller->GenericDiskInfo, + DAC960_KernelDevice(Controller->ControllerNumber, + LogicalDriveNumber, 0), + DAC960_MaxPartitions, &DAC960_BlockDeviceOperations, + Controller->V1.LogicalDriveInformation + [LogicalDriveNumber].LogicalDriveSize); + } + else + { + DAC960_V2_LogicalDeviceInfo_T *LogicalDeviceInfo = + Controller->V2.LogicalDeviceInformation[LogicalDriveNumber]; + if (LogicalDeviceInfo == NULL) return; + register_disk(&Controller->GenericDiskInfo, + DAC960_KernelDevice(Controller->ControllerNumber, + LogicalDriveNumber, 0), + DAC960_MaxPartitions, &DAC960_BlockDeviceOperations, + LogicalDeviceInfo + ->ConfigurableDeviceSizeIn512ByteBlocksOrMB); + } +} + + +/* + DAC960_ReportErrorStatus reports Controller BIOS Messages passed through + the Error Status Register when the driver performs the BIOS handshaking. + It returns true for fatal errors and false otherwise. +*/ + +static boolean DAC960_ReportErrorStatus(DAC960_Controller_T *Controller, + unsigned char ErrorStatus, + unsigned char Parameter0, + unsigned char Parameter1) +{ + switch (ErrorStatus) + { + case 0x00: + DAC960_Notice("Physical Device %d:%d Not Responding\n", + Controller, Parameter1, Parameter0); + break; + case 0x08: + if (Controller->DriveSpinUpMessageDisplayed) break; + DAC960_Notice("Spinning Up Drives\n", Controller); + Controller->DriveSpinUpMessageDisplayed = true; + break; + case 0x30: + DAC960_Notice("Configuration Checksum Error\n", Controller); + break; + case 0x60: + DAC960_Notice("Mirror Race Recovery Failed\n", Controller); + break; + case 0x70: + DAC960_Notice("Mirror Race Recovery In Progress\n", Controller); + break; + case 0x90: + DAC960_Notice("Physical Device %d:%d COD Mismatch\n", + Controller, Parameter1, Parameter0); + break; + case 0xA0: + DAC960_Notice("Logical Drive Installation Aborted\n", Controller); + break; + case 0xB0: + DAC960_Notice("Mirror Race On A Critical Logical Drive\n", Controller); + break; + case 0xD0: + DAC960_Notice("New Controller Configuration Found\n", Controller); + break; + case 0xF0: + DAC960_Error("Fatal Memory Parity Error for Controller at\n", Controller); + return true; + default: + DAC960_Error("Unknown Initialization Error %02X for Controller at\n", + Controller, ErrorStatus); + return true; + } + return false; +} + + +/* + DAC960_DetectControllers detects Mylex DAC960/AcceleRAID/eXtremeRAID + PCI RAID Controllers by interrogating the PCI Configuration Space for + Controller Type. +*/ + +static void DAC960_DetectControllers(DAC960_HardwareType_T HardwareType) +{ + void (*InterruptHandler)(int, void *, Registers_T *) = NULL; + DAC960_FirmwareType_T FirmwareType = 0; + unsigned short VendorID = 0, DeviceID = 0; + unsigned int MemoryWindowSize = 0; + PCI_Device_T *PCI_Device = NULL; + switch (HardwareType) + { + case DAC960_BA_Controller: + VendorID = PCI_VENDOR_ID_MYLEX; + DeviceID = PCI_DEVICE_ID_MYLEX_DAC960_BA; + FirmwareType = DAC960_V2_Controller; + InterruptHandler = DAC960_BA_InterruptHandler; + MemoryWindowSize = DAC960_BA_RegisterWindowSize; + break; + case DAC960_LP_Controller: + VendorID = PCI_VENDOR_ID_MYLEX; + DeviceID = PCI_DEVICE_ID_MYLEX_DAC960_LP; + FirmwareType = DAC960_LP_Controller; + InterruptHandler = DAC960_LP_InterruptHandler; + MemoryWindowSize = DAC960_LP_RegisterWindowSize; + break; + case DAC960_LA_Controller: + VendorID = PCI_VENDOR_ID_DEC; + DeviceID = PCI_DEVICE_ID_DEC_21285; + FirmwareType = DAC960_V1_Controller; + InterruptHandler = DAC960_LA_InterruptHandler; + MemoryWindowSize = DAC960_LA_RegisterWindowSize; + break; + case DAC960_PG_Controller: + VendorID = PCI_VENDOR_ID_MYLEX; + DeviceID = PCI_DEVICE_ID_MYLEX_DAC960_PG; + FirmwareType = DAC960_V1_Controller; + InterruptHandler = DAC960_PG_InterruptHandler; + MemoryWindowSize = DAC960_PG_RegisterWindowSize; + break; + case DAC960_PD_Controller: + VendorID = PCI_VENDOR_ID_MYLEX; + DeviceID = PCI_DEVICE_ID_MYLEX_DAC960_PD; + FirmwareType = DAC960_V1_Controller; + InterruptHandler = DAC960_PD_InterruptHandler; + MemoryWindowSize = DAC960_PD_RegisterWindowSize; + break; + } + while ((PCI_Device = pci_find_device(VendorID, DeviceID, PCI_Device)) != NULL) + { + DAC960_Controller_T *Controller = NULL; + DAC960_IO_Address_T IO_Address = 0; + DAC960_PCI_Address_T PCI_Address = 0; + unsigned char Bus = PCI_Device->bus->number; + unsigned char DeviceFunction = PCI_Device->devfn; + unsigned char Device = DeviceFunction >> 3; + unsigned char Function = DeviceFunction & 0x7; + unsigned char ErrorStatus, Parameter0, Parameter1; + unsigned int IRQ_Channel = PCI_Device->irq; + void *BaseAddress; + if (pci_enable_device(PCI_Device) != 0) continue; + switch (HardwareType) + { + case DAC960_BA_Controller: + PCI_Address = pci_resource_start(PCI_Device, 0); + break; + case DAC960_LP_Controller: + PCI_Address = pci_resource_start(PCI_Device, 0); + break; + case DAC960_LA_Controller: + if (!(PCI_Device->subsystem_vendor == PCI_VENDOR_ID_MYLEX && + PCI_Device->subsystem_device == PCI_DEVICE_ID_MYLEX_DAC960_LA)) + continue; + PCI_Address = pci_resource_start(PCI_Device, 0); + break; + case DAC960_PG_Controller: + PCI_Address = pci_resource_start(PCI_Device, 0); + break; + case DAC960_PD_Controller: + IO_Address = pci_resource_start(PCI_Device, 0); + PCI_Address = pci_resource_start(PCI_Device, 1); + break; + } + if (DAC960_ControllerCount == DAC960_MaxControllers) + { + DAC960_Error("More than %d DAC960 Controllers detected - " + "ignoring from Controller at\n", + NULL, DAC960_MaxControllers); + goto Failure; + } + Controller = (DAC960_Controller_T *) + kmalloc(sizeof(DAC960_Controller_T), GFP_ATOMIC); + if (Controller == NULL) + { + DAC960_Error("Unable to allocate Controller structure for " + "Controller at\n", NULL); + goto Failure; + } + memset(Controller, 0, sizeof(DAC960_Controller_T)); + Controller->ControllerNumber = DAC960_ControllerCount; + init_waitqueue_head(&Controller->CommandWaitQueue); + init_waitqueue_head(&Controller->HealthStatusWaitQueue); + DAC960_Controllers[DAC960_ControllerCount++] = Controller; + DAC960_AnnounceDriver(Controller); + Controller->FirmwareType = FirmwareType; + Controller->HardwareType = HardwareType; + Controller->IO_Address = IO_Address; + Controller->PCI_Address = PCI_Address; + Controller->Bus = Bus; + Controller->Device = Device; + Controller->Function = Function; + sprintf(Controller->ControllerName, "c%d", Controller->ControllerNumber); + /* + Map the Controller Register Window. + */ + if (MemoryWindowSize < PAGE_SIZE) + MemoryWindowSize = PAGE_SIZE; + Controller->MemoryMappedAddress = + ioremap_nocache(PCI_Address & PAGE_MASK, MemoryWindowSize); + Controller->BaseAddress = + Controller->MemoryMappedAddress + (PCI_Address & ~PAGE_MASK); + if (Controller->MemoryMappedAddress == NULL) + { + DAC960_Error("Unable to map Controller Register Window for " + "Controller at\n", Controller); + goto Failure; + } + BaseAddress = Controller->BaseAddress; + switch (HardwareType) + { + case DAC960_BA_Controller: + DAC960_BA_DisableInterrupts(Controller->BaseAddress); + DAC960_BA_AcknowledgeHardwareMailboxStatus(BaseAddress); + udelay(1000); + while (DAC960_BA_InitializationInProgressP(BaseAddress)) + { + if (DAC960_BA_ReadErrorStatus(BaseAddress, &ErrorStatus, + &Parameter0, &Parameter1) && + DAC960_ReportErrorStatus(Controller, ErrorStatus, + Parameter0, Parameter1)) + goto Failure; + udelay(10); + } + if (!DAC960_V2_EnableMemoryMailboxInterface(Controller)) + { + DAC960_Error("Unable to Enable Memory Mailbox Interface " + "for Controller at\n", Controller); + goto Failure; + } + DAC960_BA_EnableInterrupts(Controller->BaseAddress); + Controller->QueueCommand = DAC960_BA_QueueCommand; + Controller->ReadControllerConfiguration = + DAC960_V2_ReadControllerConfiguration; + Controller->ReadDeviceConfiguration = + DAC960_V2_ReadDeviceConfiguration; + Controller->ReportDeviceConfiguration = + DAC960_V2_ReportDeviceConfiguration; + Controller->QueueReadWriteCommand = + DAC960_V2_QueueReadWriteCommand; + break; + case DAC960_LP_Controller: + DAC960_LP_DisableInterrupts(Controller->BaseAddress); + DAC960_LP_AcknowledgeHardwareMailboxStatus(BaseAddress); + udelay(1000); + while (DAC960_LP_InitializationInProgressP(BaseAddress)) + { + if (DAC960_LP_ReadErrorStatus(BaseAddress, &ErrorStatus, + &Parameter0, &Parameter1) && + DAC960_ReportErrorStatus(Controller, ErrorStatus, + Parameter0, Parameter1)) + goto Failure; + udelay(10); + } + if (!DAC960_V2_EnableMemoryMailboxInterface(Controller)) + { + DAC960_Error("Unable to Enable Memory Mailbox Interface " + "for Controller at\n", Controller); + goto Failure; + } + DAC960_LP_EnableInterrupts(Controller->BaseAddress); + Controller->QueueCommand = DAC960_LP_QueueCommand; + Controller->ReadControllerConfiguration = + DAC960_V2_ReadControllerConfiguration; + Controller->ReadDeviceConfiguration = + DAC960_V2_ReadDeviceConfiguration; + Controller->ReportDeviceConfiguration = + DAC960_V2_ReportDeviceConfiguration; + Controller->QueueReadWriteCommand = + DAC960_V2_QueueReadWriteCommand; + break; + case DAC960_LA_Controller: + DAC960_LA_DisableInterrupts(Controller->BaseAddress); + DAC960_LA_AcknowledgeHardwareMailboxStatus(BaseAddress); + udelay(1000); + while (DAC960_LA_InitializationInProgressP(BaseAddress)) + { + if (DAC960_LA_ReadErrorStatus(BaseAddress, &ErrorStatus, + &Parameter0, &Parameter1) && + DAC960_ReportErrorStatus(Controller, ErrorStatus, + Parameter0, Parameter1)) + goto Failure; + udelay(10); + } + if (!DAC960_V1_EnableMemoryMailboxInterface(Controller)) + { + DAC960_Error("Unable to Enable Memory Mailbox Interface " + "for Controller at\n", Controller); + goto Failure; + } + DAC960_LA_EnableInterrupts(Controller->BaseAddress); + if (Controller->V1.DualModeMemoryMailboxInterface) + Controller->QueueCommand = DAC960_LA_QueueCommandDualMode; + else Controller->QueueCommand = DAC960_LA_QueueCommandSingleMode; + Controller->ReadControllerConfiguration = + DAC960_V1_ReadControllerConfiguration; + Controller->ReadDeviceConfiguration = + DAC960_V1_ReadDeviceConfiguration; + Controller->ReportDeviceConfiguration = + DAC960_V1_ReportDeviceConfiguration; + Controller->QueueReadWriteCommand = + DAC960_V1_QueueReadWriteCommand; + break; + case DAC960_PG_Controller: + DAC960_PG_DisableInterrupts(Controller->BaseAddress); + DAC960_PG_AcknowledgeHardwareMailboxStatus(BaseAddress); + udelay(1000); + while (DAC960_PG_InitializationInProgressP(BaseAddress)) + { + if (DAC960_PG_ReadErrorStatus(BaseAddress, &ErrorStatus, + &Parameter0, &Parameter1) && + DAC960_ReportErrorStatus(Controller, ErrorStatus, + Parameter0, Parameter1)) + goto Failure; + udelay(10); + } + if (!DAC960_V1_EnableMemoryMailboxInterface(Controller)) + { + DAC960_Error("Unable to Enable Memory Mailbox Interface " + "for Controller at\n", Controller); + goto Failure; + } + DAC960_PG_EnableInterrupts(Controller->BaseAddress); + if (Controller->V1.DualModeMemoryMailboxInterface) + Controller->QueueCommand = DAC960_PG_QueueCommandDualMode; + else Controller->QueueCommand = DAC960_PG_QueueCommandSingleMode; + Controller->ReadControllerConfiguration = + DAC960_V1_ReadControllerConfiguration; + Controller->ReadDeviceConfiguration = + DAC960_V1_ReadDeviceConfiguration; + Controller->ReportDeviceConfiguration = + DAC960_V1_ReportDeviceConfiguration; + Controller->QueueReadWriteCommand = + DAC960_V1_QueueReadWriteCommand; + break; + case DAC960_PD_Controller: + request_region(Controller->IO_Address, 0x80, + Controller->FullModelName); + DAC960_PD_DisableInterrupts(BaseAddress); + DAC960_PD_AcknowledgeStatus(BaseAddress); + udelay(1000); + while (DAC960_PD_InitializationInProgressP(BaseAddress)) + { + if (DAC960_PD_ReadErrorStatus(BaseAddress, &ErrorStatus, + &Parameter0, &Parameter1) && + DAC960_ReportErrorStatus(Controller, ErrorStatus, + Parameter0, Parameter1)) + goto Failure; + udelay(10); + } + DAC960_PD_EnableInterrupts(Controller->BaseAddress); + Controller->QueueCommand = DAC960_PD_QueueCommand; + Controller->ReadControllerConfiguration = + DAC960_V1_ReadControllerConfiguration; + Controller->ReadDeviceConfiguration = + DAC960_V1_ReadDeviceConfiguration; + Controller->ReportDeviceConfiguration = + DAC960_V1_ReportDeviceConfiguration; + Controller->QueueReadWriteCommand = + DAC960_V1_QueueReadWriteCommand; + break; + } + /* + Acquire shared access to the IRQ Channel. + */ + if (IRQ_Channel == 0) + { + DAC960_Error("IRQ Channel %d illegal for Controller at\n", + Controller, IRQ_Channel); + goto Failure; + } + strcpy(Controller->FullModelName, "DAC960"); + if (request_irq(IRQ_Channel, InterruptHandler, SA_SHIRQ, + Controller->FullModelName, Controller) < 0) + { + DAC960_Error("Unable to acquire IRQ Channel %d for Controller at\n", + Controller, IRQ_Channel); + goto Failure; + } + Controller->IRQ_Channel = IRQ_Channel; + DAC960_ActiveControllerCount++; + Controller->InitialCommand.CommandIdentifier = 1; + Controller->InitialCommand.Controller = Controller; + Controller->Commands[0] = &Controller->InitialCommand; + Controller->FreeCommands = &Controller->InitialCommand; + Controller->ControllerDetectionSuccessful = true; + continue; + Failure: + if (IO_Address == 0) + DAC960_Error("PCI Bus %d Device %d Function %d I/O Address N/A " + "PCI Address 0x%X\n", Controller, + Bus, Device, Function, PCI_Address); + else DAC960_Error("PCI Bus %d Device %d Function %d I/O Address " + "0x%X PCI Address 0x%X\n", Controller, + Bus, Device, Function, IO_Address, PCI_Address); + if (Controller == NULL) break; + if (Controller->MemoryMappedAddress != NULL) + iounmap(Controller->MemoryMappedAddress); + if (Controller->IRQ_Channel > 0) + free_irq(IRQ_Channel, Controller); + } +} + + +/* + DAC960_SortControllers sorts the Controllers by PCI Bus and Device Number. +*/ + +static void DAC960_SortControllers(void) +{ + int ControllerNumber, LastInterchange, Bound, j; + LastInterchange = DAC960_ControllerCount-1; + while (LastInterchange > 0) + { + Bound = LastInterchange; + LastInterchange = 0; + for (j = 0; j < Bound; j++) + { + DAC960_Controller_T *Controller1 = DAC960_Controllers[j]; + DAC960_Controller_T *Controller2 = DAC960_Controllers[j+1]; + if (Controller1->Bus > Controller2->Bus || + (Controller1->Bus == Controller2->Bus && + (Controller1->Device > Controller2->Device))) + { + Controller2->ControllerNumber = j; + DAC960_Controllers[j] = Controller2; + Controller1->ControllerNumber = j+1; + DAC960_Controllers[j+1] = Controller1; + LastInterchange = j; + } + } + } + for (ControllerNumber = 0; + ControllerNumber < DAC960_ControllerCount; + ControllerNumber++) + { + DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber]; + if (!Controller->ControllerDetectionSuccessful) + { + DAC960_Controllers[ControllerNumber] = NULL; + kfree(Controller); + } + } +} + + +/* DAC960_InitializeController initializes Controller. */ @@ -1320,25 +2468,12 @@ static void DAC960_InitializeController(DAC960_Controller_T *Controller) { if (DAC960_ReadControllerConfiguration(Controller) && DAC960_ReportControllerConfiguration(Controller) && + DAC960_CreateAuxiliaryStructures(Controller) && DAC960_ReadDeviceConfiguration(Controller) && DAC960_ReportDeviceConfiguration(Controller) && DAC960_RegisterBlockDevice(Controller)) { /* - Initialize the Command structures. - */ - DAC960_Command_T *Commands = Controller->Commands; - int CommandIdentifier; - Controller->FreeCommands = NULL; - for (CommandIdentifier = 0; - CommandIdentifier < Controller->DriverQueueDepth; - CommandIdentifier++) - { - Commands[CommandIdentifier].Controller = Controller; - Commands[CommandIdentifier].Next = Controller->FreeCommands; - Controller->FreeCommands = &Commands[CommandIdentifier]; - } - /* Initialize the Monitoring Timer. */ init_timer(&Controller->MonitoringTimer); @@ -1348,7 +2483,6 @@ static void DAC960_InitializeController(DAC960_Controller_T *Controller) Controller->MonitoringTimer.function = DAC960_MonitoringTimerFunction; add_timer(&Controller->MonitoringTimer); Controller->ControllerInitialized = true; - DAC960_InitializeGenericDiskInfo(&Controller->GenericDiskInfo); } else DAC960_FinalizeController(Controller); } @@ -1363,28 +2497,46 @@ static void DAC960_FinalizeController(DAC960_Controller_T *Controller) if (Controller->ControllerInitialized) { del_timer(&Controller->MonitoringTimer); - DAC960_Notice("Flushing Cache...", Controller); - DAC960_ExecuteType3(Controller, DAC960_Flush, NULL); - DAC960_Notice("done\n", Controller); - switch (Controller->ControllerType) - { - case DAC960_V5_Controller: - if (!Controller->DualModeMemoryMailboxInterface) - DAC960_V5_SaveMemoryMailboxInfo(Controller); - break; - case DAC960_V4_Controller: - if (!Controller->DualModeMemoryMailboxInterface) - DAC960_V4_SaveMemoryMailboxInfo(Controller); - break; - case DAC960_V3_Controller: - break; + if (Controller->FirmwareType == DAC960_V1_Controller) + { + DAC960_Notice("Flushing Cache...", Controller); + DAC960_V1_ExecuteType3(Controller, DAC960_V1_Flush, NULL); + DAC960_Notice("done\n", Controller); + switch (Controller->HardwareType) + { + case DAC960_LA_Controller: + if (Controller->V1.DualModeMemoryMailboxInterface) + free_pages(Controller->MemoryMailboxPagesAddress, + Controller->MemoryMailboxPagesOrder); + else DAC960_LA_SaveMemoryMailboxInfo(Controller); + break; + case DAC960_PG_Controller: + if (Controller->V1.DualModeMemoryMailboxInterface) + free_pages(Controller->MemoryMailboxPagesAddress, + Controller->MemoryMailboxPagesOrder); + else DAC960_PG_SaveMemoryMailboxInfo(Controller); + break; + case DAC960_PD_Controller: + release_region(Controller->IO_Address, 0x80); + break; + default: + break; + } + } + else + { + DAC960_Notice("Flushing Cache...", Controller); + DAC960_V2_DeviceOperation(Controller, DAC960_V2_PauseDevice, + DAC960_V2_RAID_Controller); + DAC960_Notice("done\n", Controller); + free_pages(Controller->MemoryMailboxPagesAddress, + Controller->MemoryMailboxPagesOrder); } } free_irq(Controller->IRQ_Channel, Controller); iounmap(Controller->MemoryMappedAddress); - if (Controller->IO_Address > 0) - release_region(Controller->IO_Address, 0x80); DAC960_UnregisterBlockDevice(Controller); + DAC960_DestroyAuxiliaryStructures(Controller); DAC960_Controllers[Controller->ControllerNumber] = NULL; kfree(Controller); } @@ -1397,15 +2549,26 @@ static void DAC960_FinalizeController(DAC960_Controller_T *Controller) void DAC960_Initialize(void) { int ControllerNumber; - DAC960_DetectControllers(DAC960_V5_Controller); - DAC960_DetectControllers(DAC960_V4_Controller); - DAC960_DetectControllers(DAC960_V3_Controller); + DAC960_DetectControllers(DAC960_BA_Controller); + DAC960_DetectControllers(DAC960_LP_Controller); + DAC960_DetectControllers(DAC960_LA_Controller); + DAC960_DetectControllers(DAC960_PG_Controller); + DAC960_DetectControllers(DAC960_PD_Controller); + DAC960_SortControllers(); if (DAC960_ActiveControllerCount == 0) return; for (ControllerNumber = 0; ControllerNumber < DAC960_ControllerCount; ControllerNumber++) - if (DAC960_Controllers[ControllerNumber] != NULL) - DAC960_InitializeController(DAC960_Controllers[ControllerNumber]); + { + DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber]; + int LogicalDriveNumber; + if (Controller == NULL) continue; + DAC960_InitializeController(Controller); + for (LogicalDriveNumber = 0; + LogicalDriveNumber < DAC960_MaxLogicalDrives; + LogicalDriveNumber++) + DAC960_RegisterDisk(Controller, LogicalDriveNumber); + } DAC960_CreateProcEntries(); register_reboot_notifier(&DAC960_NotifierBlock); } @@ -1435,69 +2598,38 @@ static int DAC960_Finalize(NotifierBlock_T *NotifierBlock, /* - DAC960_ProcessRequest attempts to remove one I/O Request from Controller's - I/O Request Queue and queues it to the Controller. WaitForCommand is true if - this function should wait for a Command to become available if necessary. - This function returns true if an I/O Request was queued and false otherwise. + DAC960_V1_QueueReadWriteCommand prepares and queues a Read/Write Command for + DAC960 V1 Firmware Controllers. */ -static boolean DAC960_ProcessRequest(DAC960_Controller_T *Controller, - boolean WaitForCommand) +static void DAC960_V1_QueueReadWriteCommand(DAC960_Command_T *Command) { - struct list_head * queue_head; - IO_Request_T *Request; - DAC960_Command_T *Command; - char *RequestBuffer; - - queue_head = &blk_dev[DAC960_MAJOR + Controller->ControllerNumber].request_queue.queue_head; - while (true) - { - if (list_empty(queue_head)) return false; - Request = blkdev_entry_next_request(queue_head); - if (Request->rq_status == RQ_INACTIVE) return false; - Command = DAC960_AllocateCommand(Controller); - if (Command != NULL) break; - if (!WaitForCommand) return false; - DAC960_WaitForCommand(Controller); - } - DAC960_ClearCommand(Command); - if (Request->cmd == READ) - Command->CommandType = DAC960_ReadCommand; - else Command->CommandType = DAC960_WriteCommand; - Command->Semaphore = Request->sem; - Command->LogicalDriveNumber = DAC960_LogicalDriveNumber(Request->rq_dev); - Command->BlockNumber = - Request->sector - + Controller->GenericDiskInfo.part[MINOR(Request->rq_dev)].start_sect; - Command->BlockCount = Request->nr_sectors; - Command->SegmentCount = Request->nr_segments; - Command->BufferHeader = Request->bh; - RequestBuffer = Request->buffer; - blkdev_dequeue_request(Request); - blkdev_release_request(Request); + DAC960_Controller_T *Controller = Command->Controller; + DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; + DAC960_V1_ClearCommand(Command); if (Command->SegmentCount == 1) { - DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; if (Command->CommandType == DAC960_ReadCommand) - CommandMailbox->Type5.CommandOpcode = DAC960_Read; - else CommandMailbox->Type5.CommandOpcode = DAC960_Write; + CommandMailbox->Type5.CommandOpcode = DAC960_V1_Read; + else CommandMailbox->Type5.CommandOpcode = DAC960_V1_Write; CommandMailbox->Type5.LD.TransferLength = Command->BlockCount; CommandMailbox->Type5.LD.LogicalDriveNumber = Command->LogicalDriveNumber; CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber; - CommandMailbox->Type5.BusAddress = Virtual_to_Bus(RequestBuffer); + CommandMailbox->Type5.BusAddress = Virtual_to_Bus(Command->RequestBuffer); } else { - DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; - DAC960_ScatterGatherSegment_T - *ScatterGatherList = Command->ScatterGatherList; + DAC960_V1_ScatterGatherSegment_T + *ScatterGatherList = Command->V1.ScatterGatherList; BufferHeader_T *BufferHeader = Command->BufferHeader; char *LastDataEndPointer = NULL; int SegmentNumber = 0; if (Command->CommandType == DAC960_ReadCommand) - CommandMailbox->Type5.CommandOpcode = DAC960_ReadWithOldScatterGather; + CommandMailbox->Type5.CommandOpcode = + DAC960_V1_ReadWithOldScatterGather; else - CommandMailbox->Type5.CommandOpcode = DAC960_WriteWithOldScatterGather; + CommandMailbox->Type5.CommandOpcode = + DAC960_V1_WriteWithOldScatterGather; CommandMailbox->Type5.LD.TransferLength = Command->BlockCount; CommandMailbox->Type5.LD.LogicalDriveNumber = Command->LogicalDriveNumber; CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber; @@ -1518,7 +2650,7 @@ static boolean DAC960_ProcessRequest(DAC960_Controller_T *Controller, ScatterGatherList[SegmentNumber].SegmentByteCount = BufferHeader->b_size; LastDataEndPointer = BufferHeader->b_data + BufferHeader->b_size; - if (SegmentNumber++ > Controller->MaxScatterGatherSegments) + if (SegmentNumber++ > Controller->DriverScatterGatherLimit) panic("DAC960: Scatter/Gather Segment Overflow\n"); } BufferHeader = BufferHeader->b_reqnext; @@ -1527,167 +2659,163 @@ static boolean DAC960_ProcessRequest(DAC960_Controller_T *Controller, panic("DAC960: SegmentNumber != SegmentCount\n"); } DAC960_QueueCommand(Command); - return true; -} - - -/* - DAC960_ProcessRequests attempts to remove as many I/O Requests as possible - from Controller's I/O Request Queue and queue them to the Controller. -*/ - -static inline void DAC960_ProcessRequests(DAC960_Controller_T *Controller) -{ - int Counter = 0; - while (DAC960_ProcessRequest(Controller, Counter++ == 0)) ; -} - - -/* - DAC960_RequestFunction0 is the I/O Request Function for DAC960 Controller 0. -*/ - -static void DAC960_RequestFunction0(request_queue_t * q) -{ - DAC960_Controller_T *Controller = DAC960_Controllers[0]; - ProcessorFlags_T ProcessorFlags; - /* - Acquire exclusive access to Controller. - */ - DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags); - /* - Process I/O Requests for Controller. - */ - DAC960_ProcessRequests(Controller); - /* - Release exclusive access to Controller. - */ - DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags); -} - - -/* - DAC960_RequestFunction1 is the I/O Request Function for DAC960 Controller 1. -*/ - -static void DAC960_RequestFunction1(request_queue_t * q) -{ - DAC960_Controller_T *Controller = DAC960_Controllers[1]; - ProcessorFlags_T ProcessorFlags; - /* - Acquire exclusive access to Controller. - */ - DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags); - /* - Process I/O Requests for Controller. - */ - DAC960_ProcessRequests(Controller); - /* - Release exclusive access to Controller. - */ - DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags); -} - - -/* - DAC960_RequestFunction2 is the I/O Request Function for DAC960 Controller 2. -*/ - -static void DAC960_RequestFunction2(request_queue_t * q) -{ - DAC960_Controller_T *Controller = DAC960_Controllers[2]; - ProcessorFlags_T ProcessorFlags; - /* - Acquire exclusive access to Controller. - */ - DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags); - /* - Process I/O Requests for Controller. - */ - DAC960_ProcessRequests(Controller); - /* - Release exclusive access to Controller. - */ - DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags); } /* - DAC960_RequestFunction3 is the I/O Request Function for DAC960 Controller 3. + DAC960_V2_QueueReadWriteCommand prepares and queues a Read/Write Command for + DAC960 V2 Firmware Controllers. */ -static void DAC960_RequestFunction3(request_queue_t * q) +static void DAC960_V2_QueueReadWriteCommand(DAC960_Command_T *Command) { - DAC960_Controller_T *Controller = DAC960_Controllers[3]; - ProcessorFlags_T ProcessorFlags; - /* - Acquire exclusive access to Controller. - */ - DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags); - /* - Process I/O Requests for Controller. - */ - DAC960_ProcessRequests(Controller); - /* - Release exclusive access to Controller. - */ - DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags); + DAC960_Controller_T *Controller = Command->Controller; + DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; + DAC960_V2_ClearCommand(Command); + CommandMailbox->SCSI_10.CommandOpcode = DAC960_V2_SCSI_10; + CommandMailbox->SCSI_10.CommandControlBits.DataTransferControllerToHost = + (Command->CommandType == DAC960_ReadCommand); + CommandMailbox->SCSI_10.DataTransferSize = + Command->BlockCount << DAC960_BlockSizeBits; + CommandMailbox->SCSI_10.RequestSenseBusAddress = + Virtual_to_Bus(&Command->V2.RequestSense); + CommandMailbox->SCSI_10.PhysicalDevice = + Controller->V2.LogicalDriveToVirtualDevice[Command->LogicalDriveNumber]; + CommandMailbox->SCSI_10.RequestSenseSize = + sizeof(DAC960_SCSI_RequestSense_T); + CommandMailbox->SCSI_10.CDBLength = 10; + CommandMailbox->SCSI_10.SCSI_CDB[0] = + (Command->CommandType == DAC960_ReadCommand ? 0x28 : 0x2A); + CommandMailbox->SCSI_10.SCSI_CDB[2] = Command->BlockNumber >> 24; + CommandMailbox->SCSI_10.SCSI_CDB[3] = Command->BlockNumber >> 16; + CommandMailbox->SCSI_10.SCSI_CDB[4] = Command->BlockNumber >> 8; + CommandMailbox->SCSI_10.SCSI_CDB[5] = Command->BlockNumber; + CommandMailbox->SCSI_10.SCSI_CDB[7] = Command->BlockCount >> 8; + CommandMailbox->SCSI_10.SCSI_CDB[8] = Command->BlockCount; + if (Command->SegmentCount == 1) + { + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Virtual_to_Bus(Command->RequestBuffer); + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->SCSI_10.DataTransferSize; + } + else + { + DAC960_V2_ScatterGatherSegment_T + *ScatterGatherList = Command->V2.ScatterGatherList; + BufferHeader_T *BufferHeader = Command->BufferHeader; + char *LastDataEndPointer = NULL; + int SegmentNumber = 0; + if (Command->SegmentCount > 2) + { + CommandMailbox->SCSI_10.CommandControlBits + .AdditionalScatterGatherListMemory = true; + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ExtendedScatterGather.ScatterGatherList0Length = + Command->SegmentCount; + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ExtendedScatterGather.ScatterGatherList0Address = + Virtual_to_Bus(ScatterGatherList); + } + else + ScatterGatherList = + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ScatterGatherSegments; + while (BufferHeader != NULL) + { + if (BufferHeader->b_data == LastDataEndPointer) + { + ScatterGatherList[SegmentNumber-1].SegmentByteCount += + BufferHeader->b_size; + LastDataEndPointer += BufferHeader->b_size; + } + else + { + ScatterGatherList[SegmentNumber].SegmentDataPointer = + Virtual_to_Bus(BufferHeader->b_data); + ScatterGatherList[SegmentNumber].SegmentByteCount = + BufferHeader->b_size; + LastDataEndPointer = BufferHeader->b_data + BufferHeader->b_size; + if (SegmentNumber++ > Controller->DriverScatterGatherLimit) + panic("DAC960: Scatter/Gather Segment Overflow\n"); + } + BufferHeader = BufferHeader->b_reqnext; + } + if (SegmentNumber != Command->SegmentCount) + panic("DAC960: SegmentNumber != SegmentCount\n"); + } + DAC960_QueueCommand(Command); } /* - DAC960_RequestFunction4 is the I/O Request Function for DAC960 Controller 4. + DAC960_ProcessRequest attempts to remove one I/O Request from Controller's + I/O Request Queue and queues it to the Controller. WaitForCommand is true if + this function should wait for a Command to become available if necessary. + This function returns true if an I/O Request was queued and false otherwise. */ -static void DAC960_RequestFunction4(request_queue_t * q) +static boolean DAC960_ProcessRequest(DAC960_Controller_T *Controller, + boolean WaitForCommand) { - DAC960_Controller_T *Controller = DAC960_Controllers[4]; - ProcessorFlags_T ProcessorFlags; - /* - Acquire exclusive access to Controller. - */ - DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags); - /* - Process I/O Requests for Controller. - */ - DAC960_ProcessRequests(Controller); - /* - Release exclusive access to Controller. - */ - DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags); + RequestQueue_T *RequestQueue = Controller->RequestQueue; + ListHead_T *RequestQueueHead; + IO_Request_T *Request; + DAC960_Command_T *Command; + if (RequestQueue == NULL) return false; + RequestQueueHead = &RequestQueue->queue_head; + while (true) + { + if (list_empty(RequestQueueHead)) return false; + Request = blkdev_entry_next_request(RequestQueueHead); + Command = DAC960_AllocateCommand(Controller); + if (Command != NULL) break; + if (!WaitForCommand) return false; + DAC960_WaitForCommand(Controller); + } + if (Request->cmd == READ) + Command->CommandType = DAC960_ReadCommand; + else Command->CommandType = DAC960_WriteCommand; + Command->Semaphore = Request->sem; + Command->LogicalDriveNumber = DAC960_LogicalDriveNumber(Request->rq_dev); + Command->BlockNumber = + Request->sector + + Controller->GenericDiskInfo.part[MINOR(Request->rq_dev)].start_sect; + Command->BlockCount = Request->nr_sectors; + Command->SegmentCount = Request->nr_segments; + Command->BufferHeader = Request->bh; + Command->RequestBuffer = Request->buffer; + blkdev_dequeue_request(Request); + blkdev_release_request(Request); + DAC960_QueueReadWriteCommand(Command); + return true; } /* - DAC960_RequestFunction5 is the I/O Request Function for DAC960 Controller 5. + DAC960_ProcessRequests attempts to remove as many I/O Requests as possible + from Controller's I/O Request Queue and queue them to the Controller. */ -static void DAC960_RequestFunction5(request_queue_t * q) +static inline void DAC960_ProcessRequests(DAC960_Controller_T *Controller) { - DAC960_Controller_T *Controller = DAC960_Controllers[5]; - ProcessorFlags_T ProcessorFlags; - /* - Acquire exclusive access to Controller. - */ - DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags); - /* - Process I/O Requests for Controller. - */ - DAC960_ProcessRequests(Controller); - /* - Release exclusive access to Controller. - */ - DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags); + int Counter = 0; + while (DAC960_ProcessRequest(Controller, Counter++ == 0)) ; } /* - DAC960_RequestFunction6 is the I/O Request Function for DAC960 Controller 6. + DAC960_RequestFunction is the I/O Request Function for DAC960 Controllers. */ -static void DAC960_RequestFunction6(request_queue_t * q) +static void DAC960_RequestFunction(RequestQueue_T *RequestQueue) { - DAC960_Controller_T *Controller = DAC960_Controllers[6]; + DAC960_Controller_T *Controller = + (DAC960_Controller_T *) RequestQueue->queuedata; ProcessorFlags_T ProcessorFlags; /* Acquire exclusive access to Controller. @@ -1705,37 +2833,26 @@ static void DAC960_RequestFunction6(request_queue_t * q) /* - DAC960_RequestFunction7 is the I/O Request Function for DAC960 Controller 7. + DAC960_ProcessCompletedBuffer performs completion processing for an + individual Buffer. */ -static void DAC960_RequestFunction7(request_queue_t * q) +static inline void DAC960_ProcessCompletedBuffer(BufferHeader_T *BufferHeader, + boolean SuccessfulIO) { - DAC960_Controller_T *Controller = DAC960_Controllers[7]; - ProcessorFlags_T ProcessorFlags; - /* - Acquire exclusive access to Controller. - */ - DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags); - /* - Process I/O Requests for Controller. - */ - DAC960_ProcessRequests(Controller); - /* - Release exclusive access to Controller. - */ - DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags); + BufferHeader->b_end_io(BufferHeader, SuccessfulIO); } /* - DAC960_ReadWriteError prints an appropriate error message for Command when - an error occurs on a Read or Write operation. + DAC960_V1_ReadWriteError prints an appropriate error message for Command + when an error occurs on a Read or Write operation. */ -static void DAC960_ReadWriteError(DAC960_Command_T *Command) +static void DAC960_V1_ReadWriteError(DAC960_Command_T *Command) { DAC960_Controller_T *Controller = Command->Controller; - char *CommandName = "UNKNOWN"; + unsigned char *CommandName = "UNKNOWN"; switch (Command->CommandType) { case DAC960_ReadCommand: @@ -1751,26 +2868,26 @@ static void DAC960_ReadWriteError(DAC960_Command_T *Command) case DAC960_QueuedCommand: break; } - switch (Command->CommandStatus) + switch (Command->V1.CommandStatus) { - case DAC960_IrrecoverableDataError: + case DAC960_V1_IrrecoverableDataError: DAC960_Error("Irrecoverable Data Error on %s:\n", Controller, CommandName); break; - case DAC960_LogicalDriveNonexistentOrOffline: + case DAC960_V1_LogicalDriveNonexistentOrOffline: DAC960_Error("Logical Drive Nonexistent or Offline on %s:\n", Controller, CommandName); break; - case DAC960_AccessBeyondEndOfLogicalDrive: + case DAC960_V1_AccessBeyondEndOfLogicalDrive: DAC960_Error("Attempt to Access Beyond End of Logical Drive " "on %s:\n", Controller, CommandName); break; - case DAC960_BadDataEncountered: + case DAC960_V1_BadDataEncountered: DAC960_Error("Bad Data Encountered on %s:\n", Controller, CommandName); break; default: DAC960_Error("Unexpected Error Status %04X on %s:\n", - Controller, Command->CommandStatus, CommandName); + Controller, Command->V1.CommandStatus, CommandName); break; } DAC960_Error(" /dev/rd/c%dd%d: absolute blocks %d..%d\n", @@ -1788,33 +2905,22 @@ static void DAC960_ReadWriteError(DAC960_Command_T *Command) /* - DAC960_ProcessCompletedBuffer performs completion processing for an - individual Buffer. -*/ - -static inline void DAC960_ProcessCompletedBuffer(BufferHeader_T *BufferHeader, - boolean SuccessfulIO) -{ - BufferHeader->b_end_io(BufferHeader, SuccessfulIO); -} - - -/* - DAC960_ProcessCompletedCommand performs completion processing for Command. + DAC960_V1_ProcessCompletedCommand performs completion processing for Command + for DAC960 V1 Firmware Controllers. */ -static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) +static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command) { DAC960_Controller_T *Controller = Command->Controller; DAC960_CommandType_T CommandType = Command->CommandType; - DAC960_CommandOpcode_T CommandOpcode = - Command->CommandMailbox.Common.CommandOpcode; - DAC960_CommandStatus_T CommandStatus = Command->CommandStatus; + DAC960_V1_CommandOpcode_T CommandOpcode = + Command->V1.CommandMailbox.Common.CommandOpcode; + DAC960_V1_CommandStatus_T CommandStatus = Command->V1.CommandStatus; BufferHeader_T *BufferHeader = Command->BufferHeader; if (CommandType == DAC960_ReadCommand || CommandType == DAC960_WriteCommand) { - if (CommandStatus == DAC960_NormalCompletion) + if (CommandStatus == DAC960_V1_NormalCompletion) { /* Perform completion processing for all buffers in this I/O Request. @@ -1836,21 +2942,22 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) } add_blkdev_randomness(DAC960_MAJOR + Controller->ControllerNumber); } - else if ((CommandStatus == DAC960_IrrecoverableDataError || - CommandStatus == DAC960_BadDataEncountered) && + else if ((CommandStatus == DAC960_V1_IrrecoverableDataError || + CommandStatus == DAC960_V1_BadDataEncountered) && BufferHeader != NULL && BufferHeader->b_reqnext != NULL) { - DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; + DAC960_V1_CommandMailbox_T *CommandMailbox = + &Command->V1.CommandMailbox; if (CommandType == DAC960_ReadCommand) { Command->CommandType = DAC960_ReadRetryCommand; - CommandMailbox->Type5.CommandOpcode = DAC960_Read; + CommandMailbox->Type5.CommandOpcode = DAC960_V1_Read; } else { Command->CommandType = DAC960_WriteRetryCommand; - CommandMailbox->Type5.CommandOpcode = DAC960_Write; + CommandMailbox->Type5.CommandOpcode = DAC960_V1_Write; } Command->BlockCount = BufferHeader->b_size >> DAC960_BlockSizeBits; CommandMailbox->Type5.LD.TransferLength = Command->BlockCount; @@ -1861,8 +2968,8 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) } else { - if (CommandStatus != DAC960_LogicalDriveNonexistentOrOffline) - DAC960_ReadWriteError(Command); + if (CommandStatus != DAC960_V1_LogicalDriveNonexistentOrOffline) + DAC960_V1_ReadWriteError(Command); /* Perform completion processing for all buffers in this I/O Request. */ @@ -1891,17 +2998,18 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) /* Perform completion processing for this single buffer. */ - if (CommandStatus == DAC960_NormalCompletion) + if (CommandStatus == DAC960_V1_NormalCompletion) DAC960_ProcessCompletedBuffer(BufferHeader, true); else { - if (CommandStatus != DAC960_LogicalDriveNonexistentOrOffline) - DAC960_ReadWriteError(Command); + if (CommandStatus != DAC960_V1_LogicalDriveNonexistentOrOffline) + DAC960_V1_ReadWriteError(Command); DAC960_ProcessCompletedBuffer(BufferHeader, false); } if (NextBufferHeader != NULL) { - DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; + DAC960_V1_CommandMailbox_T *CommandMailbox = + &Command->V1.CommandMailbox; Command->BlockNumber += BufferHeader->b_size >> DAC960_BlockSizeBits; Command->BlockCount = @@ -1916,30 +3024,43 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) } } else if (CommandType == DAC960_MonitoringCommand || - CommandOpcode == DAC960_Enquiry || - CommandOpcode == DAC960_GetRebuildProgress) + CommandOpcode == DAC960_V1_Enquiry || + CommandOpcode == DAC960_V1_GetRebuildProgress) { if (CommandType != DAC960_MonitoringCommand) { - if (CommandOpcode == DAC960_Enquiry) - memcpy(&Controller->Enquiry[Controller->EnquiryIndex ^ 1], - Bus_to_Virtual(Command->CommandMailbox.Type3.BusAddress), - sizeof(DAC960_Enquiry_T)); - else if (CommandOpcode == DAC960_GetRebuildProgress) - memcpy(&Controller->RebuildProgress, - Bus_to_Virtual(Command->CommandMailbox.Type3.BusAddress), - sizeof(DAC960_RebuildProgress_T)); - } - if (CommandOpcode == DAC960_Enquiry) - { - DAC960_Enquiry_T *OldEnquiry = - &Controller->Enquiry[Controller->EnquiryIndex]; - DAC960_Enquiry_T *NewEnquiry = - &Controller->Enquiry[Controller->EnquiryIndex ^= 1]; + if (CommandOpcode == DAC960_V1_Enquiry) + memcpy(&Controller->V1.NewEnquiry, + Bus_to_Virtual(Command->V1.CommandMailbox.Type3.BusAddress), + sizeof(DAC960_V1_Enquiry_T)); + else if (CommandOpcode == DAC960_V1_GetRebuildProgress) + memcpy(&Controller->V1.RebuildProgress, + Bus_to_Virtual(Command->V1.CommandMailbox.Type3.BusAddress), + sizeof(DAC960_V1_RebuildProgress_T)); + } + if (CommandOpcode == DAC960_V1_Enquiry && + Controller->ControllerInitialized) + { + DAC960_V1_Enquiry_T *OldEnquiry = &Controller->V1.Enquiry; + DAC960_V1_Enquiry_T *NewEnquiry = &Controller->V1.NewEnquiry; unsigned int OldCriticalLogicalDriveCount = OldEnquiry->CriticalLogicalDriveCount; unsigned int NewCriticalLogicalDriveCount = NewEnquiry->CriticalLogicalDriveCount; + if (NewEnquiry->NumberOfLogicalDrives > Controller->LogicalDriveCount) + { + int LogicalDriveNumber = Controller->LogicalDriveCount; + while (LogicalDriveNumber < NewEnquiry->NumberOfLogicalDrives) + { + DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) " + "Now Exists\n", Controller, + LogicalDriveNumber, + Controller->ControllerNumber, + LogicalDriveNumber); + LogicalDriveNumber++; + } + Controller->LogicalDriveCount = LogicalDriveNumber; + } if (NewEnquiry->StatusFlags.DeferredWriteError != OldEnquiry->StatusFlags.DeferredWriteError) DAC960_Critical("Deferred Write Error Flag is now %s\n", Controller, @@ -1959,72 +3080,86 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) (jiffies - Controller->SecondaryMonitoringTime >= DAC960_SecondaryMonitoringInterval)) { - Controller->NeedLogicalDriveInformation = true; - Controller->NewEventLogSequenceNumber = + Controller->V1.NeedLogicalDriveInformation = true; + Controller->V1.NewEventLogSequenceNumber = NewEnquiry->EventLogSequenceNumber; - Controller->NeedErrorTableInformation = true; - Controller->NeedDeviceStateInformation = true; - Controller->DeviceStateChannel = 0; - Controller->DeviceStateTargetID = -1; + Controller->V1.NeedErrorTableInformation = true; + Controller->V1.NeedDeviceStateInformation = true; + Controller->V1.DeviceStateChannel = 0; + Controller->V1.DeviceStateTargetID = -1; Controller->SecondaryMonitoringTime = jiffies; } - if (NewEnquiry->RebuildFlag == DAC960_StandbyRebuildInProgress || - NewEnquiry->RebuildFlag == DAC960_BackgroundRebuildInProgress || - OldEnquiry->RebuildFlag == DAC960_StandbyRebuildInProgress || - OldEnquiry->RebuildFlag == DAC960_BackgroundRebuildInProgress) - Controller->NeedRebuildProgress = true; - if (OldEnquiry->RebuildFlag == DAC960_BackgroundCheckInProgress) + if (NewEnquiry->RebuildFlag == DAC960_V1_StandbyRebuildInProgress || + NewEnquiry->RebuildFlag + == DAC960_V1_BackgroundRebuildInProgress || + OldEnquiry->RebuildFlag == DAC960_V1_StandbyRebuildInProgress || + OldEnquiry->RebuildFlag == DAC960_V1_BackgroundRebuildInProgress) + { + Controller->V1.NeedRebuildProgress = true; + Controller->V1.RebuildProgressFirst = + (NewEnquiry->CriticalLogicalDriveCount < + OldEnquiry->CriticalLogicalDriveCount); + } + if (OldEnquiry->RebuildFlag == DAC960_V1_BackgroundCheckInProgress) switch (NewEnquiry->RebuildFlag) { - case DAC960_NoStandbyRebuildOrCheckInProgress: + case DAC960_V1_NoStandbyRebuildOrCheckInProgress: DAC960_Progress("Consistency Check Completed Successfully\n", Controller); break; - case DAC960_StandbyRebuildInProgress: - case DAC960_BackgroundRebuildInProgress: + case DAC960_V1_StandbyRebuildInProgress: + case DAC960_V1_BackgroundRebuildInProgress: break; - case DAC960_BackgroundCheckInProgress: - Controller->NeedConsistencyCheckProgress = true; + case DAC960_V1_BackgroundCheckInProgress: + Controller->V1.NeedConsistencyCheckProgress = true; break; - case DAC960_StandbyRebuildCompletedWithError: + case DAC960_V1_StandbyRebuildCompletedWithError: DAC960_Progress("Consistency Check Completed with Error\n", Controller); break; - case DAC960_BackgroundRebuildOrCheckFailed_DriveFailed: + case DAC960_V1_BackgroundRebuildOrCheckFailed_DriveFailed: DAC960_Progress("Consistency Check Failed - " - "Physical Drive Failed\n", Controller); + "Physical Device Failed\n", Controller); break; - case DAC960_BackgroundRebuildOrCheckFailed_LogicalDriveFailed: + case DAC960_V1_BackgroundRebuildOrCheckFailed_LogicalDriveFailed: DAC960_Progress("Consistency Check Failed - " "Logical Drive Failed\n", Controller); break; - case DAC960_BackgroundRebuildOrCheckFailed_OtherCauses: + case DAC960_V1_BackgroundRebuildOrCheckFailed_OtherCauses: DAC960_Progress("Consistency Check Failed - Other Causes\n", Controller); break; - case DAC960_BackgroundRebuildOrCheckSuccessfullyTerminated: + case DAC960_V1_BackgroundRebuildOrCheckSuccessfullyTerminated: DAC960_Progress("Consistency Check Successfully Terminated\n", Controller); break; } - else if (NewEnquiry->RebuildFlag == DAC960_BackgroundCheckInProgress) - Controller->NeedConsistencyCheckProgress = true; + else if (NewEnquiry->RebuildFlag + == DAC960_V1_BackgroundCheckInProgress) + Controller->V1.NeedConsistencyCheckProgress = true; + Controller->MonitoringAlertMode = + (NewEnquiry->CriticalLogicalDriveCount > 0 || + NewEnquiry->OfflineLogicalDriveCount > 0 || + NewEnquiry->DeadDriveCount > 0); if (CommandType != DAC960_MonitoringCommand && - Controller->RebuildFlagPending) + Controller->V1.RebuildFlagPending) { - DAC960_Enquiry_T *Enquiry = (DAC960_Enquiry_T *) - Bus_to_Virtual(Command->CommandMailbox.Type3.BusAddress); - Enquiry->RebuildFlag = Controller->PendingRebuildFlag; - Controller->RebuildFlagPending = false; + DAC960_V1_Enquiry_T *Enquiry = (DAC960_V1_Enquiry_T *) + Bus_to_Virtual(Command->V1.CommandMailbox.Type3.BusAddress); + Enquiry->RebuildFlag = Controller->V1.PendingRebuildFlag; + Controller->V1.RebuildFlagPending = false; } else if (CommandType == DAC960_MonitoringCommand && - NewEnquiry->RebuildFlag > DAC960_BackgroundCheckInProgress) + NewEnquiry->RebuildFlag > + DAC960_V1_BackgroundCheckInProgress) { - Controller->PendingRebuildFlag = NewEnquiry->RebuildFlag; - Controller->RebuildFlagPending = true; + Controller->V1.PendingRebuildFlag = NewEnquiry->RebuildFlag; + Controller->V1.RebuildFlagPending = true; } + memcpy(&Controller->V1.Enquiry, &Controller->V1.NewEnquiry, + sizeof(DAC960_V1_Enquiry_T)); } - else if (CommandOpcode == DAC960_PerformEventLogOperation) + else if (CommandOpcode == DAC960_V1_PerformEventLogOperation) { static char *DAC960_EventMessages[] = @@ -2041,37 +3176,39 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) "killed because of selection timeout", "killed due to SCSI phase sequence error", "killed due to unknown status" }; - DAC960_EventLogEntry_T *EventLogEntry = &Controller->EventLogEntry; + DAC960_V1_EventLogEntry_T *EventLogEntry = + &Controller->V1.EventLogEntry; if (EventLogEntry->SequenceNumber == - Controller->OldEventLogSequenceNumber) + Controller->V1.OldEventLogSequenceNumber) { unsigned char SenseKey = EventLogEntry->SenseKey; unsigned char AdditionalSenseCode = EventLogEntry->AdditionalSenseCode; unsigned char AdditionalSenseCodeQualifier = EventLogEntry->AdditionalSenseCodeQualifier; - if (SenseKey == 9 && + if (SenseKey == DAC960_SenseKey_VendorSpecific && AdditionalSenseCode == 0x80 && AdditionalSenseCodeQualifier < sizeof(DAC960_EventMessages) / sizeof(char *)) - DAC960_Critical("Physical Drive %d:%d %s\n", Controller, + DAC960_Critical("Physical Device %d:%d %s\n", Controller, EventLogEntry->Channel, EventLogEntry->TargetID, DAC960_EventMessages[ AdditionalSenseCodeQualifier]); - else if (SenseKey == 6 && AdditionalSenseCode == 0x29) + else if (SenseKey == DAC960_SenseKey_UnitAttention && + AdditionalSenseCode == 0x29) { if (Controller->MonitoringTimerCount > 0) - Controller->DeviceResetCount[EventLogEntry->Channel] - [EventLogEntry->TargetID]++; + Controller->V1.DeviceResetCount[EventLogEntry->Channel] + [EventLogEntry->TargetID]++; } - else if (!(SenseKey == 0 || - (SenseKey == 2 && + else if (!(SenseKey == DAC960_SenseKey_NoSense || + (SenseKey == DAC960_SenseKey_NotReady && AdditionalSenseCode == 0x04 && (AdditionalSenseCodeQualifier == 0x01 || AdditionalSenseCodeQualifier == 0x02)))) { - DAC960_Critical("Physical Drive %d:%d Error Log: " + DAC960_Critical("Physical Device %d:%d Error Log: " "Sense Key = %d, ASC = %02X, ASCQ = %02X\n", Controller, EventLogEntry->Channel, @@ -2079,7 +3216,7 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) SenseKey, AdditionalSenseCode, AdditionalSenseCodeQualifier); - DAC960_Critical("Physical Drive %d:%d Error Log: " + DAC960_Critical("Physical Device %d:%d Error Log: " "Information = %02X%02X%02X%02X " "%02X%02X%02X%02X\n", Controller, @@ -2095,21 +3232,19 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) EventLogEntry->CommandSpecificInformation[3]); } } - Controller->OldEventLogSequenceNumber++; + Controller->V1.OldEventLogSequenceNumber++; } - else if (CommandOpcode == DAC960_GetErrorTable) + else if (CommandOpcode == DAC960_V1_GetErrorTable) { - DAC960_ErrorTable_T *OldErrorTable = - &Controller->ErrorTable[Controller->ErrorTableIndex]; - DAC960_ErrorTable_T *NewErrorTable = - &Controller->ErrorTable[Controller->ErrorTableIndex ^= 1]; + DAC960_V1_ErrorTable_T *OldErrorTable = &Controller->V1.ErrorTable; + DAC960_V1_ErrorTable_T *NewErrorTable = &Controller->V1.NewErrorTable; int Channel, TargetID; for (Channel = 0; Channel < Controller->Channels; Channel++) - for (TargetID = 0; TargetID < DAC960_MaxTargets; TargetID++) + for (TargetID = 0; TargetID < Controller->Targets; TargetID++) { - DAC960_ErrorTableEntry_T *NewErrorEntry = + DAC960_V1_ErrorTableEntry_T *NewErrorEntry = &NewErrorTable->ErrorTableEntries[Channel][TargetID]; - DAC960_ErrorTableEntry_T *OldErrorEntry = + DAC960_V1_ErrorTableEntry_T *OldErrorEntry = &OldErrorTable->ErrorTableEntries[Channel][TargetID]; if ((NewErrorEntry->ParityErrorCount != OldErrorEntry->ParityErrorCount) || @@ -2119,7 +3254,7 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) OldErrorEntry->HardErrorCount) || (NewErrorEntry->MiscErrorCount != OldErrorEntry->MiscErrorCount)) - DAC960_Critical("Physical Drive %d:%d Errors: " + DAC960_Critical("Physical Device %d:%d Errors: " "Parity = %d, Soft = %d, " "Hard = %d, Misc = %d\n", Controller, Channel, TargetID, @@ -2128,51 +3263,49 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) NewErrorEntry->HardErrorCount, NewErrorEntry->MiscErrorCount); } + memcpy(&Controller->V1.ErrorTable, &Controller->V1.NewErrorTable, + sizeof(DAC960_V1_ErrorTable_T)); } - else if (CommandOpcode == DAC960_GetDeviceState) + else if (CommandOpcode == DAC960_V1_GetDeviceState) { - DAC960_DeviceState_T *OldDeviceState = - &Controller->DeviceState[Controller->DeviceStateIndex] - [Controller->DeviceStateChannel] - [Controller->DeviceStateTargetID]; - DAC960_DeviceState_T *NewDeviceState = - &Controller->DeviceState[Controller->DeviceStateIndex ^ 1] - [Controller->DeviceStateChannel] - [Controller->DeviceStateTargetID]; + DAC960_V1_DeviceState_T *OldDeviceState = + &Controller->V1.DeviceState[Controller->V1.DeviceStateChannel] + [Controller->V1.DeviceStateTargetID]; + DAC960_V1_DeviceState_T *NewDeviceState = + &Controller->V1.NewDeviceState; if (NewDeviceState->DeviceState != OldDeviceState->DeviceState) - DAC960_Critical("Physical Drive %d:%d is now %s\n", Controller, - Controller->DeviceStateChannel, - Controller->DeviceStateTargetID, - (NewDeviceState->DeviceState == DAC960_Device_Dead + DAC960_Critical("Physical Device %d:%d is now %s\n", Controller, + Controller->V1.DeviceStateChannel, + Controller->V1.DeviceStateTargetID, + (NewDeviceState->DeviceState + == DAC960_V1_Device_Dead ? "DEAD" : NewDeviceState->DeviceState - == DAC960_Device_WriteOnly + == DAC960_V1_Device_WriteOnly ? "WRITE-ONLY" : NewDeviceState->DeviceState - == DAC960_Device_Online + == DAC960_V1_Device_Online ? "ONLINE" : "STANDBY")); - if (OldDeviceState->DeviceState == DAC960_Device_Dead && - NewDeviceState->DeviceState != DAC960_Device_Dead) + if (OldDeviceState->DeviceState == DAC960_V1_Device_Dead && + NewDeviceState->DeviceState != DAC960_V1_Device_Dead) { - Controller->NeedDeviceInquiryInformation = true; - Controller->NeedDeviceSerialNumberInformation = true; + Controller->V1.NeedDeviceInquiryInformation = true; + Controller->V1.NeedDeviceSerialNumberInformation = true; } + memcpy(OldDeviceState, NewDeviceState, + sizeof(DAC960_V1_DeviceState_T)); } - else if (CommandOpcode == DAC960_GetLogicalDriveInformation) + else if (CommandOpcode == DAC960_V1_GetLogicalDriveInformation) { int LogicalDriveNumber; for (LogicalDriveNumber = 0; LogicalDriveNumber < Controller->LogicalDriveCount; LogicalDriveNumber++) { - DAC960_LogicalDriveInformation_T *OldLogicalDriveInformation = - &Controller->LogicalDriveInformation - [Controller->LogicalDriveInformationIndex] - [LogicalDriveNumber]; - DAC960_LogicalDriveInformation_T *NewLogicalDriveInformation = - &Controller->LogicalDriveInformation - [Controller->LogicalDriveInformationIndex ^ 1] - [LogicalDriveNumber]; + DAC960_V1_LogicalDriveInformation_T *OldLogicalDriveInformation = + &Controller->V1.LogicalDriveInformation[LogicalDriveNumber]; + DAC960_V1_LogicalDriveInformation_T *NewLogicalDriveInformation = + &Controller->V1.NewLogicalDriveInformation[LogicalDriveNumber]; if (NewLogicalDriveInformation->LogicalDriveState != OldLogicalDriveInformation->LogicalDriveState) DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) " @@ -2181,11 +3314,11 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) Controller->ControllerNumber, LogicalDriveNumber, (NewLogicalDriveInformation->LogicalDriveState - == DAC960_LogicalDrive_Online + == DAC960_V1_LogicalDrive_Online ? "ONLINE" : NewLogicalDriveInformation->LogicalDriveState - == DAC960_LogicalDrive_Critical - ? "CRITICAL" : "OFFLINE")); + == DAC960_V1_LogicalDrive_Critical + ? "CRITICAL" : "OFFLINE")); if (NewLogicalDriveInformation->WriteBack != OldLogicalDriveInformation->WriteBack) DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) " @@ -2196,22 +3329,24 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) (NewLogicalDriveInformation->WriteBack ? "WRITE BACK" : "WRITE THRU")); } - Controller->LogicalDriveInformationIndex ^= 1; + memcpy(&Controller->V1.LogicalDriveInformation, + &Controller->V1.NewLogicalDriveInformation, + sizeof(DAC960_V1_LogicalDriveInformationArray_T)); } - else if (CommandOpcode == DAC960_GetRebuildProgress) + else if (CommandOpcode == DAC960_V1_GetRebuildProgress) { unsigned int LogicalDriveNumber = - Controller->RebuildProgress.LogicalDriveNumber; + Controller->V1.RebuildProgress.LogicalDriveNumber; unsigned int LogicalDriveSize = - Controller->RebuildProgress.LogicalDriveSize; + Controller->V1.RebuildProgress.LogicalDriveSize; unsigned int BlocksCompleted = - LogicalDriveSize - Controller->RebuildProgress.RemainingBlocks; - if (CommandStatus == DAC960_NoRebuildOrCheckInProgress && - Controller->LastRebuildStatus == DAC960_NormalCompletion) - CommandStatus = DAC960_RebuildSuccessful; + LogicalDriveSize - Controller->V1.RebuildProgress.RemainingBlocks; + if (CommandStatus == DAC960_V1_NoRebuildOrCheckInProgress && + Controller->V1.LastRebuildStatus == DAC960_V1_NormalCompletion) + CommandStatus = DAC960_V1_RebuildSuccessful; switch (CommandStatus) { - case DAC960_NormalCompletion: + case DAC960_V1_NormalCompletion: Controller->EphemeralProgressMessage = true; DAC960_Progress("Rebuild in Progress: " "Logical Drive %d (/dev/rd/c%dd%d) " @@ -2223,51 +3358,51 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) / (LogicalDriveSize >> 7)); Controller->EphemeralProgressMessage = false; break; - case DAC960_RebuildFailed_LogicalDriveFailure: + case DAC960_V1_RebuildFailed_LogicalDriveFailure: DAC960_Progress("Rebuild Failed due to " "Logical Drive Failure\n", Controller); break; - case DAC960_RebuildFailed_BadBlocksOnOther: + case DAC960_V1_RebuildFailed_BadBlocksOnOther: DAC960_Progress("Rebuild Failed due to " "Bad Blocks on Other Drives\n", Controller); break; - case DAC960_RebuildFailed_NewDriveFailed: + case DAC960_V1_RebuildFailed_NewDriveFailed: DAC960_Progress("Rebuild Failed due to " "Failure of Drive Being Rebuilt\n", Controller); break; - case DAC960_NoRebuildOrCheckInProgress: + case DAC960_V1_NoRebuildOrCheckInProgress: break; - case DAC960_RebuildSuccessful: + case DAC960_V1_RebuildSuccessful: DAC960_Progress("Rebuild Completed Successfully\n", Controller); break; - case DAC960_RebuildSuccessfullyTerminated: + case DAC960_V1_RebuildSuccessfullyTerminated: DAC960_Progress("Rebuild Successfully Terminated\n", Controller); break; } - Controller->LastRebuildStatus = CommandStatus; + Controller->V1.LastRebuildStatus = CommandStatus; if (CommandType != DAC960_MonitoringCommand && - Controller->RebuildStatusPending) + Controller->V1.RebuildStatusPending) { - Command->CommandStatus = Controller->PendingRebuildStatus; - Controller->RebuildStatusPending = false; + Command->V1.CommandStatus = Controller->V1.PendingRebuildStatus; + Controller->V1.RebuildStatusPending = false; } else if (CommandType == DAC960_MonitoringCommand && - CommandStatus != DAC960_NormalCompletion && - CommandStatus != DAC960_NoRebuildOrCheckInProgress) + CommandStatus != DAC960_V1_NormalCompletion && + CommandStatus != DAC960_V1_NoRebuildOrCheckInProgress) { - Controller->PendingRebuildStatus = CommandStatus; - Controller->RebuildStatusPending = true; + Controller->V1.PendingRebuildStatus = CommandStatus; + Controller->V1.RebuildStatusPending = true; } } - else if (CommandOpcode == DAC960_RebuildStat) + else if (CommandOpcode == DAC960_V1_RebuildStat) { unsigned int LogicalDriveNumber = - Controller->RebuildProgress.LogicalDriveNumber; + Controller->V1.RebuildProgress.LogicalDriveNumber; unsigned int LogicalDriveSize = - Controller->RebuildProgress.LogicalDriveSize; + Controller->V1.RebuildProgress.LogicalDriveSize; unsigned int BlocksCompleted = - LogicalDriveSize - Controller->RebuildProgress.RemainingBlocks; - if (CommandStatus == DAC960_NormalCompletion) + LogicalDriveSize - Controller->V1.RebuildProgress.RemainingBlocks; + if (CommandStatus == DAC960_V1_NormalCompletion) { Controller->EphemeralProgressMessage = true; DAC960_Progress("Consistency Check in Progress: " @@ -2284,62 +3419,60 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) } if (CommandType == DAC960_MonitoringCommand) { - if (Controller->NewEventLogSequenceNumber - - Controller->OldEventLogSequenceNumber > 0) - { - Command->CommandMailbox.Type3E.CommandOpcode = - DAC960_PerformEventLogOperation; - Command->CommandMailbox.Type3E.OperationType = - DAC960_GetEventLogEntry; - Command->CommandMailbox.Type3E.OperationQualifier = 1; - Command->CommandMailbox.Type3E.SequenceNumber = - Controller->OldEventLogSequenceNumber; - Command->CommandMailbox.Type3E.BusAddress = - Virtual_to_Bus(&Controller->EventLogEntry); + if (Controller->V1.NewEventLogSequenceNumber + - Controller->V1.OldEventLogSequenceNumber > 0) + { + Command->V1.CommandMailbox.Type3E.CommandOpcode = + DAC960_V1_PerformEventLogOperation; + Command->V1.CommandMailbox.Type3E.OperationType = + DAC960_V1_GetEventLogEntry; + Command->V1.CommandMailbox.Type3E.OperationQualifier = 1; + Command->V1.CommandMailbox.Type3E.SequenceNumber = + Controller->V1.OldEventLogSequenceNumber; + Command->V1.CommandMailbox.Type3E.BusAddress = + Virtual_to_Bus(&Controller->V1.EventLogEntry); DAC960_QueueCommand(Command); return; } - if (Controller->NeedErrorTableInformation) + if (Controller->V1.NeedErrorTableInformation) { - Controller->NeedErrorTableInformation = false; - Command->CommandMailbox.Type3.CommandOpcode = DAC960_GetErrorTable; - Command->CommandMailbox.Type3.BusAddress = - Virtual_to_Bus( - &Controller->ErrorTable[Controller->ErrorTableIndex ^ 1]); + Controller->V1.NeedErrorTableInformation = false; + Command->V1.CommandMailbox.Type3.CommandOpcode = + DAC960_V1_GetErrorTable; + Command->V1.CommandMailbox.Type3.BusAddress = + Virtual_to_Bus(&Controller->V1.NewErrorTable); DAC960_QueueCommand(Command); return; } - if (Controller->NeedRebuildProgress && - Controller->Enquiry[Controller->EnquiryIndex] - .CriticalLogicalDriveCount < - Controller->Enquiry[Controller->EnquiryIndex ^ 1] - .CriticalLogicalDriveCount) - { - Controller->NeedRebuildProgress = false; - Command->CommandMailbox.Type3.CommandOpcode = - DAC960_GetRebuildProgress; - Command->CommandMailbox.Type3.BusAddress = - Virtual_to_Bus(&Controller->RebuildProgress); + if (Controller->V1.NeedRebuildProgress && + Controller->V1.RebuildProgressFirst) + { + Controller->V1.NeedRebuildProgress = false; + Command->V1.CommandMailbox.Type3.CommandOpcode = + DAC960_V1_GetRebuildProgress; + Command->V1.CommandMailbox.Type3.BusAddress = + Virtual_to_Bus(&Controller->V1.RebuildProgress); DAC960_QueueCommand(Command); return; } - if (Controller->NeedDeviceStateInformation) + if (Controller->V1.NeedDeviceStateInformation) { - if (Controller->NeedDeviceInquiryInformation) + if (Controller->V1.NeedDeviceInquiryInformation) { - DAC960_DCDB_T *DCDB = &Controller->MonitoringDCDB; + DAC960_V1_DCDB_T *DCDB = &Controller->V1.MonitoringDCDB; DAC960_SCSI_Inquiry_T *InquiryStandardData = - &Controller->InquiryStandardData - [Controller->DeviceStateChannel] - [Controller->DeviceStateTargetID]; + &Controller->V1.InquiryStandardData + [Controller->V1.DeviceStateChannel] + [Controller->V1.DeviceStateTargetID]; InquiryStandardData->PeripheralDeviceType = 0x1F; - Command->CommandMailbox.Type3.CommandOpcode = DAC960_DCDB; - Command->CommandMailbox.Type3.BusAddress = Virtual_to_Bus(DCDB); - DCDB->Channel = Controller->DeviceStateChannel; - DCDB->TargetID = Controller->DeviceStateTargetID; - DCDB->Direction = DAC960_DCDB_DataTransferDeviceToSystem; + Command->V1.CommandMailbox.Type3.CommandOpcode = DAC960_V1_DCDB; + Command->V1.CommandMailbox.Type3.BusAddress = + Virtual_to_Bus(DCDB); + DCDB->Channel = Controller->V1.DeviceStateChannel; + DCDB->TargetID = Controller->V1.DeviceStateTargetID; + DCDB->Direction = DAC960_V1_DCDB_DataTransferDeviceToSystem; DCDB->EarlyStatus = false; - DCDB->Timeout = DAC960_DCDB_Timeout_10_seconds; + DCDB->Timeout = DAC960_V1_DCDB_Timeout_10_seconds; DCDB->NoAutomaticRequestSense = false; DCDB->DisconnectPermitted = true; DCDB->TransferLength = sizeof(DAC960_SCSI_Inquiry_T); @@ -2354,24 +3487,25 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) DCDB->CDB[4] = sizeof(DAC960_SCSI_Inquiry_T); DCDB->CDB[5] = 0; /* Control */ DAC960_QueueCommand(Command); - Controller->NeedDeviceInquiryInformation = false; + Controller->V1.NeedDeviceInquiryInformation = false; return; } - if (Controller->NeedDeviceSerialNumberInformation) + if (Controller->V1.NeedDeviceSerialNumberInformation) { - DAC960_DCDB_T *DCDB = &Controller->MonitoringDCDB; + DAC960_V1_DCDB_T *DCDB = &Controller->V1.MonitoringDCDB; DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber = - &Controller->InquiryUnitSerialNumber - [Controller->DeviceStateChannel] - [Controller->DeviceStateTargetID]; + &Controller->V1.InquiryUnitSerialNumber + [Controller->V1.DeviceStateChannel] + [Controller->V1.DeviceStateTargetID]; InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F; - Command->CommandMailbox.Type3.CommandOpcode = DAC960_DCDB; - Command->CommandMailbox.Type3.BusAddress = Virtual_to_Bus(DCDB); - DCDB->Channel = Controller->DeviceStateChannel; - DCDB->TargetID = Controller->DeviceStateTargetID; - DCDB->Direction = DAC960_DCDB_DataTransferDeviceToSystem; + Command->V1.CommandMailbox.Type3.CommandOpcode = DAC960_V1_DCDB; + Command->V1.CommandMailbox.Type3.BusAddress = + Virtual_to_Bus(DCDB); + DCDB->Channel = Controller->V1.DeviceStateChannel; + DCDB->TargetID = Controller->V1.DeviceStateTargetID; + DCDB->Direction = DAC960_V1_DCDB_DataTransferDeviceToSystem; DCDB->EarlyStatus = false; - DCDB->Timeout = DAC960_DCDB_Timeout_10_seconds; + DCDB->Timeout = DAC960_V1_DCDB_Timeout_10_seconds; DCDB->NoAutomaticRequestSense = false; DCDB->DisconnectPermitted = true; DCDB->TransferLength = @@ -2387,74 +3521,68 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) DCDB->CDB[4] = sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); DCDB->CDB[5] = 0; /* Control */ DAC960_QueueCommand(Command); - Controller->NeedDeviceSerialNumberInformation = false; + Controller->V1.NeedDeviceSerialNumberInformation = false; return; } - if (++Controller->DeviceStateTargetID == DAC960_MaxTargets) + if (++Controller->V1.DeviceStateTargetID == Controller->Targets) { - Controller->DeviceStateChannel++; - Controller->DeviceStateTargetID = 0; + Controller->V1.DeviceStateChannel++; + Controller->V1.DeviceStateTargetID = 0; } - while (Controller->DeviceStateChannel < Controller->Channels) + while (Controller->V1.DeviceStateChannel < Controller->Channels) { - DAC960_DeviceState_T *OldDeviceState = - &Controller->DeviceState[Controller->DeviceStateIndex] - [Controller->DeviceStateChannel] - [Controller->DeviceStateTargetID]; + DAC960_V1_DeviceState_T *OldDeviceState = + &Controller->V1.DeviceState[Controller->V1.DeviceStateChannel] + [Controller->V1.DeviceStateTargetID]; if (OldDeviceState->Present && - OldDeviceState->DeviceType == DAC960_DiskType) + OldDeviceState->DeviceType == DAC960_V1_DiskType) { - Command->CommandMailbox.Type3D.CommandOpcode = - DAC960_GetDeviceState; - Command->CommandMailbox.Type3D.Channel = - Controller->DeviceStateChannel; - Command->CommandMailbox.Type3D.TargetID = - Controller->DeviceStateTargetID; - Command->CommandMailbox.Type3D.BusAddress = - Virtual_to_Bus(&Controller->DeviceState - [Controller->DeviceStateIndex ^ 1] - [Controller->DeviceStateChannel] - [Controller->DeviceStateTargetID]); + Command->V1.CommandMailbox.Type3D.CommandOpcode = + DAC960_V1_GetDeviceState; + Command->V1.CommandMailbox.Type3D.Channel = + Controller->V1.DeviceStateChannel; + Command->V1.CommandMailbox.Type3D.TargetID = + Controller->V1.DeviceStateTargetID; + Command->V1.CommandMailbox.Type3D.BusAddress = + Virtual_to_Bus(&Controller->V1.NewDeviceState); DAC960_QueueCommand(Command); return; } - if (++Controller->DeviceStateTargetID == DAC960_MaxTargets) + if (++Controller->V1.DeviceStateTargetID == Controller->Targets) { - Controller->DeviceStateChannel++; - Controller->DeviceStateTargetID = 0; + Controller->V1.DeviceStateChannel++; + Controller->V1.DeviceStateTargetID = 0; } } - Controller->NeedDeviceStateInformation = false; - Controller->DeviceStateIndex ^= 1; - } - if (Controller->NeedLogicalDriveInformation) - { - Controller->NeedLogicalDriveInformation = false; - Command->CommandMailbox.Type3.CommandOpcode = - DAC960_GetLogicalDriveInformation; - Command->CommandMailbox.Type3.BusAddress = - Virtual_to_Bus( - &Controller->LogicalDriveInformation - [Controller->LogicalDriveInformationIndex ^ 1]); + Controller->V1.NeedDeviceStateInformation = false; + } + if (Controller->V1.NeedLogicalDriveInformation) + { + Controller->V1.NeedLogicalDriveInformation = false; + Command->V1.CommandMailbox.Type3.CommandOpcode = + DAC960_V1_GetLogicalDriveInformation; + Command->V1.CommandMailbox.Type3.BusAddress = + Virtual_to_Bus(&Controller->V1.NewLogicalDriveInformation); DAC960_QueueCommand(Command); return; } - if (Controller->NeedRebuildProgress) + if (Controller->V1.NeedRebuildProgress) { - Controller->NeedRebuildProgress = false; - Command->CommandMailbox.Type3.CommandOpcode = - DAC960_GetRebuildProgress; - Command->CommandMailbox.Type3.BusAddress = - Virtual_to_Bus(&Controller->RebuildProgress); + Controller->V1.NeedRebuildProgress = false; + Command->V1.CommandMailbox.Type3.CommandOpcode = + DAC960_V1_GetRebuildProgress; + Command->V1.CommandMailbox.Type3.BusAddress = + Virtual_to_Bus(&Controller->V1.RebuildProgress); DAC960_QueueCommand(Command); return; } - if (Controller->NeedConsistencyCheckProgress) + if (Controller->V1.NeedConsistencyCheckProgress) { - Controller->NeedConsistencyCheckProgress = false; - Command->CommandMailbox.Type3.CommandOpcode = DAC960_RebuildStat; - Command->CommandMailbox.Type3.BusAddress = - Virtual_to_Bus(&Controller->RebuildProgress); + Controller->V1.NeedConsistencyCheckProgress = false; + Command->V1.CommandMailbox.Type3.CommandOpcode = + DAC960_V1_RebuildStat; + Command->V1.CommandMailbox.Type3.BusAddress = + Virtual_to_Bus(&Controller->V1.RebuildProgress); DAC960_QueueCommand(Command); return; } @@ -2471,12 +3599,835 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) } if (CommandType == DAC960_QueuedCommand) { - DAC960_KernelCommand_T *KernelCommand = Command->KernelCommand; - KernelCommand->CommandStatus = Command->CommandStatus; - Command->KernelCommand = NULL; - if (CommandOpcode == DAC960_DCDB) - Controller->DirectCommandActive[KernelCommand->DCDB->Channel] - [KernelCommand->DCDB->TargetID] = false; + DAC960_V1_KernelCommand_T *KernelCommand = Command->V1.KernelCommand; + KernelCommand->CommandStatus = Command->V1.CommandStatus; + Command->V1.KernelCommand = NULL; + if (CommandOpcode == DAC960_V1_DCDB) + Controller->V1.DirectCommandActive[KernelCommand->DCDB->Channel] + [KernelCommand->DCDB->TargetID] = + false; + DAC960_DeallocateCommand(Command); + KernelCommand->CompletionFunction(KernelCommand); + return; + } + /* + Queue a Status Monitoring Command to the Controller using the just + completed Command if one was deferred previously due to lack of a + free Command when the Monitoring Timer Function was called. + */ + if (Controller->MonitoringCommandDeferred) + { + Controller->MonitoringCommandDeferred = false; + DAC960_V1_QueueMonitoringCommand(Command); + return; + } + /* + Deallocate the Command. + */ + DAC960_DeallocateCommand(Command); + /* + Wake up any processes waiting on a free Command. + */ + wake_up(&Controller->CommandWaitQueue); +} + + +/* + DAC960_V2_ReadWriteError prints an appropriate error message for Command + when an error occurs on a Read or Write operation. +*/ + +static void DAC960_V2_ReadWriteError(DAC960_Command_T *Command) +{ + DAC960_Controller_T *Controller = Command->Controller; + unsigned char *SenseErrors[] = { "NO SENSE", "RECOVERED ERROR", + "NOT READY", "MEDIUM ERROR", + "HARDWARE ERROR", "ILLEGAL REQUEST", + "UNIT ATTENTION", "DATA PROTECT", + "BLANK CHECK", "VENDOR-SPECIFIC", + "COPY ABORTED", "ABORTED COMMAND", + "EQUAL", "VOLUME OVERFLOW", + "MISCOMPARE", "RESERVED" }; + unsigned char *CommandName = "UNKNOWN"; + switch (Command->CommandType) + { + case DAC960_ReadCommand: + case DAC960_ReadRetryCommand: + CommandName = "READ"; + break; + case DAC960_WriteCommand: + case DAC960_WriteRetryCommand: + CommandName = "WRITE"; + break; + case DAC960_MonitoringCommand: + case DAC960_ImmediateCommand: + case DAC960_QueuedCommand: + break; + } + DAC960_Error("Error Condition %s on %s:\n", Controller, + SenseErrors[Command->V2.RequestSense.SenseKey], CommandName); + DAC960_Error(" /dev/rd/c%dd%d: absolute blocks %d..%d\n", + Controller, Controller->ControllerNumber, + Command->LogicalDriveNumber, Command->BlockNumber, + Command->BlockNumber + Command->BlockCount - 1); + if (DAC960_PartitionNumber(Command->BufferHeader->b_rdev) > 0) + DAC960_Error(" /dev/rd/c%dd%dp%d: relative blocks %d..%d\n", + Controller, Controller->ControllerNumber, + Command->LogicalDriveNumber, + DAC960_PartitionNumber(Command->BufferHeader->b_rdev), + Command->BufferHeader->b_rsector, + Command->BufferHeader->b_rsector + Command->BlockCount - 1); +} + + +/* + DAC960_V2_ReportEvent prints an appropriate message when a Controller Event + occurs. +*/ + +static void DAC960_V2_ReportEvent(DAC960_Controller_T *Controller, + DAC960_V2_Event_T *Event) +{ + DAC960_SCSI_RequestSense_T *RequestSense = + (DAC960_SCSI_RequestSense_T *) &Event->RequestSenseData; + unsigned char MessageBuffer[DAC960_LineBufferSize]; + static struct { int EventCode; unsigned char *EventMessage; } EventList[] = + { /* Physical Device Events (0x0000 - 0x007F) */ + { 0x0001, "P Online" }, + { 0x0002, "P Standby" }, + { 0x0005, "P Automatic Rebuild Started" }, + { 0x0006, "P Manual Rebuild Started" }, + { 0x0007, "P Rebuild Completed" }, + { 0x0008, "P Rebuild Cancelled" }, + { 0x0009, "P Rebuild Failed for Unknown Reasons" }, + { 0x000A, "P Rebuild Failed due to New Physical Device" }, + { 0x000B, "P Rebuild Failed due to Logical Drive Failure" }, + { 0x000C, "S Offline" }, + { 0x000D, "P Found" }, + { 0x000E, "P Gone" }, + { 0x000F, "P Unconfigured" }, + { 0x0010, "P Expand Capacity Started" }, + { 0x0011, "P Expand Capacity Completed" }, + { 0x0012, "P Expand Capacity Failed" }, + { 0x0016, "P Parity Error" }, + { 0x0017, "P Soft Error" }, + { 0x0018, "P Miscellaneous Error" }, + { 0x0019, "P Reset" }, + { 0x001A, "P Active Spare Found" }, + { 0x001B, "P Warm Spare Found" }, + { 0x001C, "S Sense Data Received" }, + { 0x001D, "P Initialization Started" }, + { 0x001E, "P Initialization Completed" }, + { 0x001F, "P Initialization Failed" }, + { 0x0020, "P Initialization Cancelled" }, + { 0x0021, "P Failed because Write Recovery Failed" }, + { 0x0022, "P Failed because SCSI Bus Reset Failed" }, + { 0x0023, "P Failed because of Double Check Condition" }, + { 0x0024, "P Failed because Device Cannot Be Accessed" }, + { 0x0025, "P Failed because of Gross Error on SCSI Processor" }, + { 0x0026, "P Failed because of Bad Tag from Device" }, + { 0x0027, "P Failed because of Command Timeout" }, + { 0x0028, "P Failed because of System Reset" }, + { 0x0029, "P Failed because of Busy Status or Parity Error" }, + { 0x002A, "P Failed because Host Set Device to Failed State" }, + { 0x002B, "P Failed because of Selection Timeout" }, + { 0x002C, "P Failed because of SCSI Bus Phase Error" }, + { 0x002D, "P Failed because Device Returned Unknown Status" }, + { 0x002E, "P Failed because Device Not Ready" }, + { 0x002F, "P Failed because Device Not Found at Startup" }, + { 0x0030, "P Failed because COD Write Operation Failed" }, + { 0x0031, "P Failed because BDT Write Operation Failed" }, + { 0x0039, "P Missing at Startup" }, + { 0x003A, "P Start Rebuild Failed due to Physical Drive Too Small" }, + /* Logical Device Events (0x0080 - 0x00FF) */ + { 0x0080, "M Consistency Check Started" }, + { 0x0081, "M Consistency Check Completed" }, + { 0x0082, "M Consistency Check Cancelled" }, + { 0x0083, "M Consistency Check Completed With Errors" }, + { 0x0084, "M Consistency Check Failed due to Logical Drive Failure" }, + { 0x0085, "M Consistency Check Failed due to Physical Device Failure" }, + { 0x0086, "L Offline" }, + { 0x0087, "L Critical" }, + { 0x0088, "L Online" }, + { 0x0089, "M Automatic Rebuild Started" }, + { 0x008A, "M Manual Rebuild Started" }, + { 0x008B, "M Rebuild Completed" }, + { 0x008C, "M Rebuild Cancelled" }, + { 0x008D, "M Rebuild Failed for Unknown Reasons" }, + { 0x008E, "M Rebuild Failed due to New Physical Device" }, + { 0x008F, "M Rebuild Failed due to Logical Drive Failure" }, + { 0x0090, "L Initialization Started" }, + { 0x0091, "L Initialization Completed" }, + { 0x0092, "L Initialization Cancelled" }, + { 0x0093, "L Initialization Failed" }, + { 0x0094, "L Found" }, + { 0x0095, "L Gone" }, + { 0x0096, "L Expand Capacity Started" }, + { 0x0097, "L Expand Capacity Completed" }, + { 0x0098, "L Expand Capacity Failed" }, + { 0x0099, "L Bad Block Found" }, + { 0x009A, "L Size Changed" }, + { 0x009B, "L Type Changed" }, + { 0x009C, "L Bad Data Block Found" }, + { 0x009E, "L Read of Data Block in BDT" }, + { 0x009F, "L Write Back Data for Disk Block Lost" }, + /* Fault Management Events (0x0100 - 0x017F) */ + { 0x0140, "E Fan %d Failed" }, + { 0x0141, "E Fan %d OK" }, + { 0x0142, "E Fan %d Not Present" }, + { 0x0143, "E Power Supply %d Failed" }, + { 0x0144, "E Power Supply %d OK" }, + { 0x0145, "E Power Supply %d Not Present" }, + { 0x0146, "E Temperature Sensor %d Failed" }, + { 0x0147, "E Temperature Sensor %d Critical" }, + { 0x0148, "E Temperature Sensor %d OK" }, + { 0x0149, "E Temperature Sensor %d Not Present" }, + { 0x014A, "E Unit %d Access Critical" }, + { 0x014B, "E Unit %d Access OK" }, + { 0x014C, "E Unit %d Access Offline" }, + /* Controller Events (0x0180 - 0x01FF) */ + { 0x0181, "C Cache Write Back Error" }, + { 0x0188, "C Battery Backup Unit Found" }, + { 0x0189, "C Battery Backup Unit Charge Level Low" }, + { 0x018A, "C Battery Backup Unit Charge Level OK" }, + { 0x0193, "C Installation Aborted" }, + { 0x0195, "C Mirror Race Recovery In Progress" }, + { 0x0196, "C Mirror Race on Critical Drive" }, + { 0x019E, "C Memory Soft ECC Error" }, + { 0x019F, "C Memory Hard ECC Error" }, + { 0x01A2, "C Battery Backup Unit Failed" }, + { 0, "" } }; + int EventListIndex = 0, EventCode; + unsigned char EventType, *EventMessage; + while (true) + { + EventCode = EventList[EventListIndex].EventCode; + if (EventCode == Event->EventCode || EventCode == 0) break; + EventListIndex++; + } + EventType = EventList[EventListIndex].EventMessage[0]; + EventMessage = &EventList[EventListIndex].EventMessage[2]; + if (EventCode == 0) + { + DAC960_Critical("Unknown Controller Event Code %04X\n", + Controller, Event->EventCode); + return; + } + switch (EventType) + { + case 'P': + DAC960_Critical("Physical Device %d:%d %s\n", Controller, + Event->Channel, Event->TargetID, EventMessage); + break; + case 'L': + DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) %s\n", Controller, + Event->LogicalUnit, Controller->ControllerNumber, + Event->LogicalUnit, EventMessage); + break; + case 'M': + DAC960_Progress("Logical Drive %d (/dev/rd/c%dd%d) %s\n", Controller, + Event->LogicalUnit, Controller->ControllerNumber, + Event->LogicalUnit, EventMessage); + break; + case 'S': + if (RequestSense->SenseKey == DAC960_SenseKey_NoSense || + (RequestSense->SenseKey == DAC960_SenseKey_NotReady && + RequestSense->AdditionalSenseCode == 0x04 && + (RequestSense->AdditionalSenseCodeQualifier == 0x01 || + RequestSense->AdditionalSenseCodeQualifier == 0x02))) + break; + DAC960_Critical("Physical Device %d:%d %s\n", Controller, + Event->Channel, Event->TargetID, EventMessage); + DAC960_Critical("Physical Device %d:%d Request Sense: " + "Sense Key = %d, ASC = %02X, ASCQ = %02X\n", + Controller, + Event->Channel, + Event->TargetID, + RequestSense->SenseKey, + RequestSense->AdditionalSenseCode, + RequestSense->AdditionalSenseCodeQualifier); + DAC960_Critical("Physical Device %d:%d Request Sense: " + "Information = %02X%02X%02X%02X " + "%02X%02X%02X%02X\n", + Controller, + Event->Channel, + Event->TargetID, + RequestSense->Information[0], + RequestSense->Information[1], + RequestSense->Information[2], + RequestSense->Information[3], + RequestSense->CommandSpecificInformation[0], + RequestSense->CommandSpecificInformation[1], + RequestSense->CommandSpecificInformation[2], + RequestSense->CommandSpecificInformation[3]); + break; + case 'E': + sprintf(MessageBuffer, EventMessage, Event->LogicalUnit); + DAC960_Critical("Enclosure %d %s\n", Controller, + Event->TargetID, MessageBuffer); + break; + case 'C': + DAC960_Critical("Controller %s\n", Controller, EventMessage); + break; + default: + DAC960_Critical("Unknown Controller Event Code %04X\n", + Controller, Event->EventCode); + break; + } +} + + +/* + DAC960_V2_ReportProgress prints an appropriate progress message for + Logical Device Long Operations. +*/ + +static void DAC960_V2_ReportProgress(DAC960_Controller_T *Controller, + unsigned char *MessageString, + unsigned int LogicalDeviceNumber, + unsigned long BlocksCompleted, + unsigned long LogicalDeviceSize) +{ + Controller->EphemeralProgressMessage = true; + DAC960_Progress("%s in Progress: Logical Drive %d (/dev/rd/c%dd%d) " + "%d%% completed\n", Controller, + MessageString, + LogicalDeviceNumber, + Controller->ControllerNumber, + LogicalDeviceNumber, + (100 * (BlocksCompleted >> 7)) / (LogicalDeviceSize >> 7)); + Controller->EphemeralProgressMessage = false; +} + + +/* + DAC960_V2_ProcessCompletedCommand performs completion processing for Command + for DAC960 V2 Firmware Controllers. +*/ + +static void DAC960_V2_ProcessCompletedCommand(DAC960_Command_T *Command) +{ + DAC960_Controller_T *Controller = Command->Controller; + DAC960_CommandType_T CommandType = Command->CommandType; + DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; + DAC960_V2_IOCTL_Opcode_T CommandOpcode = CommandMailbox->Common.IOCTL_Opcode; + DAC960_V2_CommandStatus_T CommandStatus = Command->V2.CommandStatus; + BufferHeader_T *BufferHeader = Command->BufferHeader; + if (CommandType == DAC960_ReadCommand || + CommandType == DAC960_WriteCommand) + { + if (CommandStatus == DAC960_V2_NormalCompletion) + { + /* + Perform completion processing for all buffers in this I/O Request. + */ + while (BufferHeader != NULL) + { + BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext; + BufferHeader->b_reqnext = NULL; + DAC960_ProcessCompletedBuffer(BufferHeader, true); + BufferHeader = NextBufferHeader; + } + /* + Wake up requestor for swap file paging requests. + */ + if (Command->Semaphore != NULL) + { + up(Command->Semaphore); + Command->Semaphore = NULL; + } + add_blkdev_randomness(DAC960_MAJOR + Controller->ControllerNumber); + } + else if (Command->V2.RequestSense.SenseKey + == DAC960_SenseKey_MediumError && + BufferHeader != NULL && + BufferHeader->b_reqnext != NULL) + { + if (CommandType == DAC960_ReadCommand) + Command->CommandType = DAC960_ReadRetryCommand; + else Command->CommandType = DAC960_WriteRetryCommand; + Command->BlockCount = BufferHeader->b_size >> DAC960_BlockSizeBits; + CommandMailbox->SCSI_10.CommandControlBits + .AdditionalScatterGatherListMemory = false; + CommandMailbox->SCSI_10.DataTransferSize = + Command->BlockCount << DAC960_BlockSizeBits; + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ScatterGatherSegments[0].SegmentDataPointer = + Virtual_to_Bus(BufferHeader->b_data); + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ScatterGatherSegments[0].SegmentByteCount = + CommandMailbox->SCSI_10.DataTransferSize; + CommandMailbox->SCSI_10.SCSI_CDB[7] = Command->BlockCount >> 8; + CommandMailbox->SCSI_10.SCSI_CDB[8] = Command->BlockCount; + DAC960_QueueCommand(Command); + return; + } + else + { + if (Command->V2.RequestSense.SenseKey != DAC960_SenseKey_NotReady) + DAC960_V2_ReadWriteError(Command); + /* + Perform completion processing for all buffers in this I/O Request. + */ + while (BufferHeader != NULL) + { + BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext; + BufferHeader->b_reqnext = NULL; + DAC960_ProcessCompletedBuffer(BufferHeader, false); + BufferHeader = NextBufferHeader; + } + /* + Wake up requestor for swap file paging requests. + */ + if (Command->Semaphore != NULL) + { + up(Command->Semaphore); + Command->Semaphore = NULL; + } + } + } + else if (CommandType == DAC960_ReadRetryCommand || + CommandType == DAC960_WriteRetryCommand) + { + BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext; + BufferHeader->b_reqnext = NULL; + /* + Perform completion processing for this single buffer. + */ + if (CommandStatus == DAC960_V2_NormalCompletion) + DAC960_ProcessCompletedBuffer(BufferHeader, true); + else + { + if (Command->V2.RequestSense.SenseKey != DAC960_SenseKey_NotReady) + DAC960_V2_ReadWriteError(Command); + DAC960_ProcessCompletedBuffer(BufferHeader, false); + } + if (NextBufferHeader != NULL) + { + Command->BlockNumber += + BufferHeader->b_size >> DAC960_BlockSizeBits; + Command->BlockCount = + NextBufferHeader->b_size >> DAC960_BlockSizeBits; + Command->BufferHeader = NextBufferHeader; + CommandMailbox->SCSI_10.DataTransferSize = + Command->BlockCount << DAC960_BlockSizeBits; + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Virtual_to_Bus(NextBufferHeader->b_data); + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->SCSI_10.DataTransferSize; + CommandMailbox->SCSI_10.SCSI_CDB[2] = Command->BlockNumber >> 24; + CommandMailbox->SCSI_10.SCSI_CDB[3] = Command->BlockNumber >> 16; + CommandMailbox->SCSI_10.SCSI_CDB[4] = Command->BlockNumber >> 8; + CommandMailbox->SCSI_10.SCSI_CDB[5] = Command->BlockNumber; + CommandMailbox->SCSI_10.SCSI_CDB[7] = Command->BlockCount >> 8; + CommandMailbox->SCSI_10.SCSI_CDB[8] = Command->BlockCount; + DAC960_QueueCommand(Command); + return; + } + } + else if (CommandType == DAC960_MonitoringCommand) + { + if (CommandOpcode == DAC960_V2_GetControllerInfo) + { + DAC960_V2_ControllerInfo_T *NewControllerInfo = + &Controller->V2.NewControllerInformation; + DAC960_V2_ControllerInfo_T *ControllerInfo = + &Controller->V2.ControllerInformation; + Controller->LogicalDriveCount = + NewControllerInfo->LogicalDevicesPresent; + Controller->V2.NeedLogicalDeviceInformation = true; + Controller->V2.NewLogicalDeviceInformation.LogicalDeviceNumber = 0; + Controller->V2.NeedPhysicalDeviceInformation = true; + Controller->V2.PhysicalDeviceIndex = 0; + Controller->V2.NewPhysicalDeviceInformation.Channel = 0; + Controller->V2.NewPhysicalDeviceInformation.TargetID = 0; + Controller->V2.NewPhysicalDeviceInformation.LogicalUnit = 0; + Controller->MonitoringAlertMode = + (NewControllerInfo->LogicalDevicesCritical > 0 || + NewControllerInfo->LogicalDevicesOffline > 0 || + NewControllerInfo->PhysicalDisksCritical > 0 || + NewControllerInfo->PhysicalDisksOffline > 0); + memcpy(ControllerInfo, NewControllerInfo, + sizeof(DAC960_V2_ControllerInfo_T)); + } + else if (CommandOpcode == DAC960_V2_GetEvent) + { + if (CommandStatus == DAC960_V2_NormalCompletion) + DAC960_V2_ReportEvent(Controller, &Controller->V2.Event); + Controller->V2.NextEventSequenceNumber++; + } + else if (CommandOpcode == DAC960_V2_GetPhysicalDeviceInfoValid && + CommandStatus == DAC960_V2_NormalCompletion) + { + DAC960_V2_PhysicalDeviceInfo_T *NewPhysicalDeviceInfo = + &Controller->V2.NewPhysicalDeviceInformation; + unsigned int PhysicalDeviceIndex = Controller->V2.PhysicalDeviceIndex; + DAC960_V2_PhysicalDeviceInfo_T *PhysicalDeviceInfo = + Controller->V2.PhysicalDeviceInformation[PhysicalDeviceIndex]; + DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber; + if (PhysicalDeviceInfo == NULL || + (NewPhysicalDeviceInfo->Channel != + PhysicalDeviceInfo->Channel) || + (NewPhysicalDeviceInfo->TargetID != + PhysicalDeviceInfo->TargetID) || + (NewPhysicalDeviceInfo->LogicalUnit != + PhysicalDeviceInfo->LogicalUnit)) + { + unsigned int DeviceIndex; + PhysicalDeviceInfo = (DAC960_V2_PhysicalDeviceInfo_T *) + kmalloc(sizeof(DAC960_V2_PhysicalDeviceInfo_T), GFP_ATOMIC); + InquiryUnitSerialNumber = + (DAC960_SCSI_Inquiry_UnitSerialNumber_T *) + kmalloc(sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T), + GFP_ATOMIC); + if (InquiryUnitSerialNumber == NULL) + { + kfree(PhysicalDeviceInfo); + PhysicalDeviceInfo = NULL; + } + DAC960_Critical("Physical Device %d:%d Now Exists%s\n", + Controller, + NewPhysicalDeviceInfo->Channel, + NewPhysicalDeviceInfo->TargetID, + (PhysicalDeviceInfo != NULL + ? "" : " - Allocation Failed")); + if (PhysicalDeviceInfo != NULL) + { + for (DeviceIndex = PhysicalDeviceIndex; + DeviceIndex < DAC960_V2_MaxPhysicalDevices - 1; + DeviceIndex++) + { + Controller->V2.PhysicalDeviceInformation[DeviceIndex+1] = + Controller->V2.PhysicalDeviceInformation[DeviceIndex]; + Controller->V2.InquiryUnitSerialNumber[DeviceIndex+1] = + Controller->V2.InquiryUnitSerialNumber[DeviceIndex]; + Controller->V2.PhysicalDeviceInformation + [PhysicalDeviceIndex] = + PhysicalDeviceInfo; + Controller->V2.InquiryUnitSerialNumber + [PhysicalDeviceIndex] = + InquiryUnitSerialNumber; + } + memset(PhysicalDeviceInfo, 0, + sizeof(DAC960_V2_PhysicalDeviceInfo_T)); + PhysicalDeviceInfo->PhysicalDeviceState = + DAC960_V2_Device_InvalidState; + memset(InquiryUnitSerialNumber, 0, + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T)); + InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F; + Controller->V2.NeedDeviceSerialNumberInformation = true; + } + } + if (PhysicalDeviceInfo != NULL) + { + if (NewPhysicalDeviceInfo->PhysicalDeviceState != + PhysicalDeviceInfo->PhysicalDeviceState) + DAC960_Critical("Physical Device %d:%d is now %s\n", Controller, + NewPhysicalDeviceInfo->Channel, + NewPhysicalDeviceInfo->TargetID, + (NewPhysicalDeviceInfo->PhysicalDeviceState + == DAC960_V2_Device_Unconfigured + ? "UNCONFIGURED" + : NewPhysicalDeviceInfo->PhysicalDeviceState + == DAC960_V2_Device_Online + ? "ONLINE" + : NewPhysicalDeviceInfo->PhysicalDeviceState + == DAC960_V2_Device_WriteOnly + ? "WRITE-ONLY" + : NewPhysicalDeviceInfo + ->PhysicalDeviceState + == DAC960_V2_Device_Dead + ? "DEAD" : "STANDBY")); + if ((NewPhysicalDeviceInfo->ParityErrors != + PhysicalDeviceInfo->ParityErrors) || + (NewPhysicalDeviceInfo->SoftErrors != + PhysicalDeviceInfo->SoftErrors) || + (NewPhysicalDeviceInfo->HardErrors != + PhysicalDeviceInfo->HardErrors) || + (NewPhysicalDeviceInfo->MiscellaneousErrors != + PhysicalDeviceInfo->MiscellaneousErrors) || + (NewPhysicalDeviceInfo->CommandTimeouts != + PhysicalDeviceInfo->CommandTimeouts) || + (NewPhysicalDeviceInfo->Retries != + PhysicalDeviceInfo->Retries) || + (NewPhysicalDeviceInfo->Aborts != + PhysicalDeviceInfo->Aborts) || + (NewPhysicalDeviceInfo->PredictedFailuresDetected != + PhysicalDeviceInfo->PredictedFailuresDetected)) + { + DAC960_Critical("Physical Device %d:%d Errors: " + "Parity = %d, Soft = %d, " + "Hard = %d, Misc = %d\n", + Controller, + NewPhysicalDeviceInfo->Channel, + NewPhysicalDeviceInfo->TargetID, + NewPhysicalDeviceInfo->ParityErrors, + NewPhysicalDeviceInfo->SoftErrors, + NewPhysicalDeviceInfo->HardErrors, + NewPhysicalDeviceInfo->MiscellaneousErrors); + DAC960_Critical("Physical Device %d:%d Errors: " + "Timeouts = %d, Retries = %d, " + "Aborts = %d, Predicted = %d\n", + Controller, + NewPhysicalDeviceInfo->Channel, + NewPhysicalDeviceInfo->TargetID, + NewPhysicalDeviceInfo->CommandTimeouts, + NewPhysicalDeviceInfo->Retries, + NewPhysicalDeviceInfo->Aborts, + NewPhysicalDeviceInfo + ->PredictedFailuresDetected); + } + if (PhysicalDeviceInfo->PhysicalDeviceState + == DAC960_V2_Device_Dead && + NewPhysicalDeviceInfo->PhysicalDeviceState + != DAC960_V2_Device_Dead) + Controller->V2.NeedDeviceSerialNumberInformation = true; + memcpy(PhysicalDeviceInfo, NewPhysicalDeviceInfo, + sizeof(DAC960_V2_PhysicalDeviceInfo_T)); + } + NewPhysicalDeviceInfo->LogicalUnit++; + Controller->V2.PhysicalDeviceIndex++; + } + else if (CommandOpcode == DAC960_V2_GetPhysicalDeviceInfoValid) + Controller->V2.NeedPhysicalDeviceInformation = false; + else if (CommandOpcode == DAC960_V2_GetLogicalDeviceInfoValid && + CommandStatus == DAC960_V2_NormalCompletion) + { + DAC960_V2_LogicalDeviceInfo_T *NewLogicalDeviceInfo = + &Controller->V2.NewLogicalDeviceInformation; + unsigned short LogicalDeviceNumber = + NewLogicalDeviceInfo->LogicalDeviceNumber; + DAC960_V2_LogicalDeviceInfo_T *LogicalDeviceInfo = + Controller->V2.LogicalDeviceInformation[LogicalDeviceNumber]; + if (LogicalDeviceInfo == NULL) + { + DAC960_V2_PhysicalDevice_T PhysicalDevice; + PhysicalDevice.Controller = 0; + PhysicalDevice.Channel = NewLogicalDeviceInfo->Channel; + PhysicalDevice.TargetID = NewLogicalDeviceInfo->TargetID; + PhysicalDevice.LogicalUnit = NewLogicalDeviceInfo->LogicalUnit; + Controller->V2.LogicalDriveToVirtualDevice[LogicalDeviceNumber] = + PhysicalDevice; + LogicalDeviceInfo = (DAC960_V2_LogicalDeviceInfo_T *) + kmalloc(sizeof(DAC960_V2_LogicalDeviceInfo_T), GFP_ATOMIC); + Controller->V2.LogicalDeviceInformation[LogicalDeviceNumber] = + LogicalDeviceInfo; + DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) " + "Now Exists%s\n", Controller, + LogicalDeviceNumber, + Controller->ControllerNumber, + LogicalDeviceNumber, + (LogicalDeviceInfo != NULL + ? "" : " - Allocation Failed")); + if (LogicalDeviceInfo != NULL) + memset(LogicalDeviceInfo, 0, + sizeof(DAC960_V2_LogicalDeviceInfo_T)); + } + if (LogicalDeviceInfo != NULL) + { + unsigned long LogicalDeviceSize = + NewLogicalDeviceInfo->ConfigurableDeviceSizeIn512ByteBlocksOrMB; + if (NewLogicalDeviceInfo->LogicalDeviceState != + LogicalDeviceInfo->LogicalDeviceState) + DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) " + "is now %s\n", Controller, + LogicalDeviceNumber, + Controller->ControllerNumber, + LogicalDeviceNumber, + (NewLogicalDeviceInfo->LogicalDeviceState + == DAC960_V2_LogicalDevice_Online + ? "ONLINE" + : NewLogicalDeviceInfo->LogicalDeviceState + == DAC960_V2_LogicalDevice_Critical + ? "CRITICAL" : "OFFLINE")); + if ((NewLogicalDeviceInfo->SoftErrors != + LogicalDeviceInfo->SoftErrors) || + (NewLogicalDeviceInfo->CommandsFailed != + LogicalDeviceInfo->CommandsFailed) || + (NewLogicalDeviceInfo->DeferredWriteErrors != + LogicalDeviceInfo->DeferredWriteErrors)) + DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) Errors: " + "Soft = %d, Failed = %d, Deferred Write = %d\n", + Controller, LogicalDeviceNumber, + Controller->ControllerNumber, + LogicalDeviceNumber, + NewLogicalDeviceInfo->SoftErrors, + NewLogicalDeviceInfo->CommandsFailed, + NewLogicalDeviceInfo->DeferredWriteErrors); + if (NewLogicalDeviceInfo->ConsistencyCheckInProgress) + DAC960_V2_ReportProgress(Controller, + "Consistency Check", + LogicalDeviceNumber, + NewLogicalDeviceInfo + ->ConsistencyCheckBlockNumber, + LogicalDeviceSize); + else if (NewLogicalDeviceInfo->RebuildInProgress) + DAC960_V2_ReportProgress(Controller, + "Rebuild", + LogicalDeviceNumber, + NewLogicalDeviceInfo + ->RebuildBlockNumber, + LogicalDeviceSize); + else if (NewLogicalDeviceInfo->BackgroundInitializationInProgress) + DAC960_V2_ReportProgress(Controller, + "BackgroundInitialization", + LogicalDeviceNumber, + NewLogicalDeviceInfo + ->BackgroundInitializationBlockNumber, + LogicalDeviceSize); + else if (NewLogicalDeviceInfo->ForegroundInitializationInProgress) + DAC960_V2_ReportProgress(Controller, + "Foreground Initialization", + LogicalDeviceNumber, + NewLogicalDeviceInfo + ->ForegroundInitializationBlockNumber, + LogicalDeviceSize); + else if (NewLogicalDeviceInfo->DataMigrationInProgress) + DAC960_V2_ReportProgress(Controller, + "Data Migration", + LogicalDeviceNumber, + NewLogicalDeviceInfo + ->DataMigrationBlockNumber, + LogicalDeviceSize); + else if (NewLogicalDeviceInfo->PatrolOperationInProgress) + DAC960_V2_ReportProgress(Controller, + "Patrol Operation", + LogicalDeviceNumber, + NewLogicalDeviceInfo + ->PatrolOperationBlockNumber, + LogicalDeviceSize); + memcpy(LogicalDeviceInfo, NewLogicalDeviceInfo, + sizeof(DAC960_V2_LogicalDeviceInfo_T)); + } + NewLogicalDeviceInfo->LogicalDeviceNumber++; + } + else if (CommandOpcode == DAC960_V2_GetLogicalDeviceInfoValid) + Controller->V2.NeedLogicalDeviceInformation = false; + if (Controller->V2.HealthStatusBuffer->NextEventSequenceNumber + - Controller->V2.NextEventSequenceNumber > 0) + { + CommandMailbox->GetEvent.CommandOpcode = DAC960_V2_IOCTL; + CommandMailbox->GetEvent.DataTransferSize = sizeof(DAC960_V2_Event_T); + CommandMailbox->GetEvent.EventSequenceNumberHigh16 = + Controller->V2.NextEventSequenceNumber >> 16; + CommandMailbox->GetEvent.ControllerNumber = 0; + CommandMailbox->GetEvent.IOCTL_Opcode = + DAC960_V2_GetEvent; + CommandMailbox->GetEvent.EventSequenceNumberLow16 = + Controller->V2.NextEventSequenceNumber & 0xFFFF; + CommandMailbox->GetEvent.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Virtual_to_Bus(&Controller->V2.Event); + CommandMailbox->GetEvent.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->GetEvent.DataTransferSize; + DAC960_QueueCommand(Command); + return; + } + if (Controller->V2.NeedPhysicalDeviceInformation) + { + if (Controller->V2.NeedDeviceSerialNumberInformation) + { + DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber = + Controller->V2.InquiryUnitSerialNumber + [Controller->V2.PhysicalDeviceIndex - 1]; + InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F; + CommandMailbox->SCSI_10.CommandOpcode = + DAC960_V2_SCSI_10_Passthru; + CommandMailbox->SCSI_10.DataTransferSize = + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); + CommandMailbox->SCSI_10.PhysicalDevice.LogicalUnit = + Controller->V2.NewPhysicalDeviceInformation.LogicalUnit - 1; + CommandMailbox->SCSI_10.PhysicalDevice.TargetID = + Controller->V2.NewPhysicalDeviceInformation.TargetID; + CommandMailbox->SCSI_10.PhysicalDevice.Channel = + Controller->V2.NewPhysicalDeviceInformation.Channel; + CommandMailbox->SCSI_10.CDBLength = 6; + CommandMailbox->SCSI_10.SCSI_CDB[0] = 0x12; /* INQUIRY */ + CommandMailbox->SCSI_10.SCSI_CDB[1] = 1; /* EVPD = 1 */ + CommandMailbox->SCSI_10.SCSI_CDB[2] = 0x80; /* Page Code */ + CommandMailbox->SCSI_10.SCSI_CDB[3] = 0; /* Reserved */ + CommandMailbox->SCSI_10.SCSI_CDB[4] = + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); + CommandMailbox->SCSI_10.SCSI_CDB[5] = 0; /* Control */ + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Virtual_to_Bus(InquiryUnitSerialNumber); + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->SCSI_10.DataTransferSize; + DAC960_QueueCommand(Command); + Controller->V2.NeedDeviceSerialNumberInformation = false; + return; + } + CommandMailbox->PhysicalDeviceInfo.CommandOpcode = DAC960_V2_IOCTL; + CommandMailbox->PhysicalDeviceInfo.DataTransferSize = + sizeof(DAC960_V2_PhysicalDeviceInfo_T); + CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.LogicalUnit = + Controller->V2.NewPhysicalDeviceInformation.LogicalUnit; + CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.TargetID = + Controller->V2.NewPhysicalDeviceInformation.TargetID; + CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.Channel = + Controller->V2.NewPhysicalDeviceInformation.Channel; + CommandMailbox->PhysicalDeviceInfo.IOCTL_Opcode = + DAC960_V2_GetPhysicalDeviceInfoValid; + CommandMailbox->PhysicalDeviceInfo.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Virtual_to_Bus(&Controller->V2.NewPhysicalDeviceInformation); + CommandMailbox->PhysicalDeviceInfo.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->PhysicalDeviceInfo.DataTransferSize; + DAC960_QueueCommand(Command); + return; + } + if (Controller->V2.NeedLogicalDeviceInformation) + { + CommandMailbox->LogicalDeviceInfo.CommandOpcode = DAC960_V2_IOCTL; + CommandMailbox->LogicalDeviceInfo.DataTransferSize = + sizeof(DAC960_V2_LogicalDeviceInfo_T); + CommandMailbox->LogicalDeviceInfo.LogicalDevice.LogicalDeviceNumber = + Controller->V2.NewLogicalDeviceInformation.LogicalDeviceNumber; + CommandMailbox->LogicalDeviceInfo.IOCTL_Opcode = + DAC960_V2_GetLogicalDeviceInfoValid; + CommandMailbox->LogicalDeviceInfo.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Virtual_to_Bus(&Controller->V2.NewLogicalDeviceInformation); + CommandMailbox->LogicalDeviceInfo.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->LogicalDeviceInfo.DataTransferSize; + DAC960_QueueCommand(Command); + return; + } + Controller->MonitoringTimerCount++; + Controller->MonitoringTimer.expires = + jiffies + DAC960_HealthStatusMonitoringInterval; + add_timer(&Controller->MonitoringTimer); + } + if (CommandType == DAC960_ImmediateCommand) + { + up(Command->Semaphore); + Command->Semaphore = NULL; + return; + } + if (CommandType == DAC960_QueuedCommand) + { + DAC960_V2_KernelCommand_T *KernelCommand = Command->V2.KernelCommand; + KernelCommand->CommandStatus = CommandStatus; + KernelCommand->RequestSenseLength = Command->V2.RequestSenseLength; + KernelCommand->DataTransferLength = Command->V2.DataTransferResidue; + Command->V2.KernelCommand = NULL; DAC960_DeallocateCommand(Command); KernelCommand->CompletionFunction(KernelCommand); return; @@ -2489,7 +4440,7 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) if (Controller->MonitoringCommandDeferred) { Controller->MonitoringCommandDeferred = false; - DAC960_QueueMonitoringCommand(Command); + DAC960_V2_QueueMonitoringCommand(Command); return; } /* @@ -2504,16 +4455,17 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) /* - DAC960_InterruptHandler handles hardware interrupts from DAC960 Controllers. + DAC960_BA_InterruptHandler handles hardware interrupts from DAC960 BA Series + Controllers. */ -static void DAC960_InterruptHandler(int IRQ_Channel, - void *DeviceIdentifier, - Registers_T *InterruptRegisters) +static void DAC960_BA_InterruptHandler(int IRQ_Channel, + void *DeviceIdentifier, + Registers_T *InterruptRegisters) { DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier; void *ControllerBaseAddress = Controller->BaseAddress; - DAC960_StatusMailbox_T *NextStatusMailbox; + DAC960_V2_StatusMailbox_T *NextStatusMailbox; ProcessorFlags_T ProcessorFlags; /* Acquire exclusive access to Controller. @@ -2522,54 +4474,24 @@ static void DAC960_InterruptHandler(int IRQ_Channel, /* Process Hardware Interrupts for Controller. */ - switch (Controller->ControllerType) - { - case DAC960_V5_Controller: - DAC960_V5_AcknowledgeInterrupt(ControllerBaseAddress); - NextStatusMailbox = Controller->NextStatusMailbox; - while (NextStatusMailbox->Fields.Valid) - { - DAC960_CommandIdentifier_T CommandIdentifier = - NextStatusMailbox->Fields.CommandIdentifier; - DAC960_Command_T *Command = &Controller->Commands[CommandIdentifier]; - Command->CommandStatus = NextStatusMailbox->Fields.CommandStatus; - NextStatusMailbox->Word = 0; - if (++NextStatusMailbox > Controller->LastStatusMailbox) - NextStatusMailbox = Controller->FirstStatusMailbox; - DAC960_ProcessCompletedCommand(Command); - } - Controller->NextStatusMailbox = NextStatusMailbox; - break; - case DAC960_V4_Controller: - DAC960_V4_AcknowledgeInterrupt(ControllerBaseAddress); - NextStatusMailbox = Controller->NextStatusMailbox; - while (NextStatusMailbox->Fields.Valid) - { - DAC960_CommandIdentifier_T CommandIdentifier = - NextStatusMailbox->Fields.CommandIdentifier; - DAC960_Command_T *Command = &Controller->Commands[CommandIdentifier]; - Command->CommandStatus = NextStatusMailbox->Fields.CommandStatus; - NextStatusMailbox->Word = 0; - if (++NextStatusMailbox > Controller->LastStatusMailbox) - NextStatusMailbox = Controller->FirstStatusMailbox; - DAC960_ProcessCompletedCommand(Command); - } - Controller->NextStatusMailbox = NextStatusMailbox; - break; - case DAC960_V3_Controller: - while (DAC960_V3_StatusAvailableP(ControllerBaseAddress)) - { - DAC960_CommandIdentifier_T CommandIdentifier = - DAC960_V3_ReadStatusCommandIdentifier(ControllerBaseAddress); - DAC960_Command_T *Command = &Controller->Commands[CommandIdentifier]; - Command->CommandStatus = - DAC960_V3_ReadStatusRegister(ControllerBaseAddress); - DAC960_V3_AcknowledgeInterrupt(ControllerBaseAddress); - DAC960_V3_AcknowledgeStatus(ControllerBaseAddress); - DAC960_ProcessCompletedCommand(Command); - } - break; + DAC960_BA_AcknowledgeInterrupt(ControllerBaseAddress); + NextStatusMailbox = Controller->V2.NextStatusMailbox; + while (NextStatusMailbox->Fields.CommandIdentifier > 0) + { + DAC960_V2_CommandIdentifier_T CommandIdentifier = + NextStatusMailbox->Fields.CommandIdentifier; + DAC960_Command_T *Command = Controller->Commands[CommandIdentifier-1]; + Command->V2.CommandStatus = NextStatusMailbox->Fields.CommandStatus; + Command->V2.RequestSenseLength = + NextStatusMailbox->Fields.RequestSenseLength; + Command->V2.DataTransferResidue = + NextStatusMailbox->Fields.DataTransferResidue; + NextStatusMailbox->Words[0] = 0; + if (++NextStatusMailbox > Controller->V2.LastStatusMailbox) + NextStatusMailbox = Controller->V2.FirstStatusMailbox; + DAC960_V2_ProcessCompletedCommand(Command); } + Controller->V2.NextStatusMailbox = NextStatusMailbox; /* Attempt to remove additional I/O Requests from the Controller's I/O Request Queue and queue them to the Controller. @@ -2583,47 +4505,311 @@ static void DAC960_InterruptHandler(int IRQ_Channel, /* - DAC960_QueueMonitoringCommand queues a Monitoring Command to Controller. + DAC960_LP_InterruptHandler handles hardware interrupts from DAC960 LP Series + Controllers. */ -static void DAC960_QueueMonitoringCommand(DAC960_Command_T *Command) +static void DAC960_LP_InterruptHandler(int IRQ_Channel, + void *DeviceIdentifier, + Registers_T *InterruptRegisters) { - DAC960_Controller_T *Controller = Command->Controller; - DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; - DAC960_ClearCommand(Command); - Command->CommandType = DAC960_MonitoringCommand; - CommandMailbox->Type3.CommandOpcode = DAC960_Enquiry; - CommandMailbox->Type3.BusAddress = - Virtual_to_Bus(&Controller->Enquiry[Controller->EnquiryIndex ^ 1]); - DAC960_QueueCommand(Command); + DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier; + void *ControllerBaseAddress = Controller->BaseAddress; + DAC960_V2_StatusMailbox_T *NextStatusMailbox; + ProcessorFlags_T ProcessorFlags; + /* + Acquire exclusive access to Controller. + */ + DAC960_AcquireControllerLockIH(Controller, &ProcessorFlags); + /* + Process Hardware Interrupts for Controller. + */ + DAC960_LP_AcknowledgeInterrupt(ControllerBaseAddress); + NextStatusMailbox = Controller->V2.NextStatusMailbox; + while (NextStatusMailbox->Fields.CommandIdentifier > 0) + { + DAC960_V2_CommandIdentifier_T CommandIdentifier = + NextStatusMailbox->Fields.CommandIdentifier; + DAC960_Command_T *Command = Controller->Commands[CommandIdentifier-1]; + Command->V2.CommandStatus = NextStatusMailbox->Fields.CommandStatus; + Command->V2.RequestSenseLength = + NextStatusMailbox->Fields.RequestSenseLength; + Command->V2.DataTransferResidue = + NextStatusMailbox->Fields.DataTransferResidue; + NextStatusMailbox->Words[0] = 0; + if (++NextStatusMailbox > Controller->V2.LastStatusMailbox) + NextStatusMailbox = Controller->V2.FirstStatusMailbox; + DAC960_V2_ProcessCompletedCommand(Command); + } + Controller->V2.NextStatusMailbox = NextStatusMailbox; + /* + Attempt to remove additional I/O Requests from the Controller's + I/O Request Queue and queue them to the Controller. + */ + while (DAC960_ProcessRequest(Controller, false)) ; + /* + Release exclusive access to Controller. + */ + DAC960_ReleaseControllerLockIH(Controller, &ProcessorFlags); } /* - DAC960_MonitoringTimerFunction is the timer function for monitoring - the status of DAC960 Controllers. + DAC960_LA_InterruptHandler handles hardware interrupts from DAC960 LA Series + Controllers. */ -static void DAC960_MonitoringTimerFunction(unsigned long TimerData) +static void DAC960_LA_InterruptHandler(int IRQ_Channel, + void *DeviceIdentifier, + Registers_T *InterruptRegisters) { - DAC960_Controller_T *Controller = (DAC960_Controller_T *) TimerData; - DAC960_Command_T *Command; + DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier; + void *ControllerBaseAddress = Controller->BaseAddress; + DAC960_V1_StatusMailbox_T *NextStatusMailbox; ProcessorFlags_T ProcessorFlags; /* Acquire exclusive access to Controller. */ - DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + DAC960_AcquireControllerLockIH(Controller, &ProcessorFlags); /* - Queue a Status Monitoring Command to Controller. + Process Hardware Interrupts for Controller. */ - Command = DAC960_AllocateCommand(Controller); - if (Command != NULL) - DAC960_QueueMonitoringCommand(Command); - else Controller->MonitoringCommandDeferred = true; + DAC960_LA_AcknowledgeInterrupt(ControllerBaseAddress); + NextStatusMailbox = Controller->V1.NextStatusMailbox; + while (NextStatusMailbox->Fields.Valid) + { + DAC960_V1_CommandIdentifier_T CommandIdentifier = + NextStatusMailbox->Fields.CommandIdentifier; + DAC960_Command_T *Command = Controller->Commands[CommandIdentifier-1]; + Command->V1.CommandStatus = NextStatusMailbox->Fields.CommandStatus; + NextStatusMailbox->Word = 0; + if (++NextStatusMailbox > Controller->V1.LastStatusMailbox) + NextStatusMailbox = Controller->V1.FirstStatusMailbox; + DAC960_V1_ProcessCompletedCommand(Command); + } + Controller->V1.NextStatusMailbox = NextStatusMailbox; + /* + Attempt to remove additional I/O Requests from the Controller's + I/O Request Queue and queue them to the Controller. + */ + while (DAC960_ProcessRequest(Controller, false)) ; /* Release exclusive access to Controller. */ - DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + DAC960_ReleaseControllerLockIH(Controller, &ProcessorFlags); +} + + +/* + DAC960_PG_InterruptHandler handles hardware interrupts from DAC960 PG Series + Controllers. +*/ + +static void DAC960_PG_InterruptHandler(int IRQ_Channel, + void *DeviceIdentifier, + Registers_T *InterruptRegisters) +{ + DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier; + void *ControllerBaseAddress = Controller->BaseAddress; + DAC960_V1_StatusMailbox_T *NextStatusMailbox; + ProcessorFlags_T ProcessorFlags; + /* + Acquire exclusive access to Controller. + */ + DAC960_AcquireControllerLockIH(Controller, &ProcessorFlags); + /* + Process Hardware Interrupts for Controller. + */ + DAC960_PG_AcknowledgeInterrupt(ControllerBaseAddress); + NextStatusMailbox = Controller->V1.NextStatusMailbox; + while (NextStatusMailbox->Fields.Valid) + { + DAC960_V1_CommandIdentifier_T CommandIdentifier = + NextStatusMailbox->Fields.CommandIdentifier; + DAC960_Command_T *Command = Controller->Commands[CommandIdentifier-1]; + Command->V1.CommandStatus = NextStatusMailbox->Fields.CommandStatus; + NextStatusMailbox->Word = 0; + if (++NextStatusMailbox > Controller->V1.LastStatusMailbox) + NextStatusMailbox = Controller->V1.FirstStatusMailbox; + DAC960_V1_ProcessCompletedCommand(Command); + } + Controller->V1.NextStatusMailbox = NextStatusMailbox; + /* + Attempt to remove additional I/O Requests from the Controller's + I/O Request Queue and queue them to the Controller. + */ + while (DAC960_ProcessRequest(Controller, false)) ; + /* + Release exclusive access to Controller. + */ + DAC960_ReleaseControllerLockIH(Controller, &ProcessorFlags); +} + + +/* + DAC960_PD_InterruptHandler handles hardware interrupts from DAC960 PD Series + Controllers. +*/ + +static void DAC960_PD_InterruptHandler(int IRQ_Channel, + void *DeviceIdentifier, + Registers_T *InterruptRegisters) +{ + DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier; + void *ControllerBaseAddress = Controller->BaseAddress; + ProcessorFlags_T ProcessorFlags; + /* + Acquire exclusive access to Controller. + */ + DAC960_AcquireControllerLockIH(Controller, &ProcessorFlags); + /* + Process Hardware Interrupts for Controller. + */ + while (DAC960_PD_StatusAvailableP(ControllerBaseAddress)) + { + DAC960_V1_CommandIdentifier_T CommandIdentifier = + DAC960_PD_ReadStatusCommandIdentifier(ControllerBaseAddress); + DAC960_Command_T *Command = Controller->Commands[CommandIdentifier-1]; + Command->V1.CommandStatus = + DAC960_PD_ReadStatusRegister(ControllerBaseAddress); + DAC960_PD_AcknowledgeInterrupt(ControllerBaseAddress); + DAC960_PD_AcknowledgeStatus(ControllerBaseAddress); + DAC960_V1_ProcessCompletedCommand(Command); + } + /* + Attempt to remove additional I/O Requests from the Controller's + I/O Request Queue and queue them to the Controller. + */ + while (DAC960_ProcessRequest(Controller, false)) ; + /* + Release exclusive access to Controller. + */ + DAC960_ReleaseControllerLockIH(Controller, &ProcessorFlags); +} + + +/* + DAC960_V1_QueueMonitoringCommand queues a Monitoring Command to DAC960 V1 + Firmware Controllers. +*/ + +static void DAC960_V1_QueueMonitoringCommand(DAC960_Command_T *Command) +{ + DAC960_Controller_T *Controller = Command->Controller; + DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; + DAC960_V1_ClearCommand(Command); + Command->CommandType = DAC960_MonitoringCommand; + CommandMailbox->Type3.CommandOpcode = DAC960_V1_Enquiry; + CommandMailbox->Type3.BusAddress = Virtual_to_Bus(&Controller->V1.NewEnquiry); + DAC960_QueueCommand(Command); +} + + +/* + DAC960_V2_QueueMonitoringCommand queues a Monitoring Command to DAC960 V2 + Firmware Controllers. +*/ + +static void DAC960_V2_QueueMonitoringCommand(DAC960_Command_T *Command) +{ + DAC960_Controller_T *Controller = Command->Controller; + DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; + DAC960_V2_ClearCommand(Command); + Command->CommandType = DAC960_MonitoringCommand; + CommandMailbox->ControllerInfo.CommandOpcode = DAC960_V2_IOCTL; + CommandMailbox->ControllerInfo.CommandControlBits + .DataTransferControllerToHost = true; + CommandMailbox->ControllerInfo.CommandControlBits + .NoAutoRequestSense = true; + CommandMailbox->ControllerInfo.DataTransferSize = + sizeof(DAC960_V2_ControllerInfo_T); + CommandMailbox->ControllerInfo.ControllerNumber = 0; + CommandMailbox->ControllerInfo.IOCTL_Opcode = DAC960_V2_GetControllerInfo; + CommandMailbox->ControllerInfo.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Virtual_to_Bus(&Controller->V2.NewControllerInformation); + CommandMailbox->ControllerInfo.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->ControllerInfo.DataTransferSize; + DAC960_QueueCommand(Command); +} + + +/* + DAC960_MonitoringTimerFunction is the timer function for monitoring + the status of DAC960 Controllers. +*/ + +static void DAC960_MonitoringTimerFunction(unsigned long TimerData) +{ + DAC960_Controller_T *Controller = (DAC960_Controller_T *) TimerData; + DAC960_Command_T *Command; + ProcessorFlags_T ProcessorFlags; + if (Controller->FirmwareType == DAC960_V1_Controller) + { + /* + Acquire exclusive access to Controller. + */ + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + /* + Queue a Status Monitoring Command to Controller. + */ + Command = DAC960_AllocateCommand(Controller); + if (Command != NULL) + DAC960_V1_QueueMonitoringCommand(Command); + else Controller->MonitoringCommandDeferred = true; + /* + Release exclusive access to Controller. + */ + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + } + else + { + DAC960_V2_ControllerInfo_T *ControllerInfo = + &Controller->V2.ControllerInformation; + unsigned int StatusChangeCounter = + Controller->V2.HealthStatusBuffer->StatusChangeCounter; + if (StatusChangeCounter == Controller->V2.StatusChangeCounter && + Controller->V2.HealthStatusBuffer->NextEventSequenceNumber + == Controller->V2.NextEventSequenceNumber && + (ControllerInfo->BackgroundInitializationsActive + + ControllerInfo->LogicalDeviceInitializationsActive + + ControllerInfo->PhysicalDeviceInitializationsActive + + ControllerInfo->ConsistencyChecksActive + + ControllerInfo->RebuildsActive + + ControllerInfo->OnlineExpansionsActive == 0 || + jiffies - Controller->PrimaryMonitoringTime + < DAC960_MonitoringTimerInterval)) + { + Controller->MonitoringTimer.expires = + jiffies + DAC960_HealthStatusMonitoringInterval; + add_timer(&Controller->MonitoringTimer); + return; + } + Controller->V2.StatusChangeCounter = StatusChangeCounter; + Controller->PrimaryMonitoringTime = jiffies; + /* + Acquire exclusive access to Controller. + */ + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + /* + Queue a Status Monitoring Command to Controller. + */ + Command = DAC960_AllocateCommand(Controller); + if (Command != NULL) + DAC960_V2_QueueMonitoringCommand(Command); + else Controller->MonitoringCommandDeferred = true; + /* + Release exclusive access to Controller. + */ + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + /* + Wake up any processes waiting on a Health Status Buffer change. + */ + wake_up(&Controller->HealthStatusWaitQueue); + } } @@ -2642,20 +4828,29 @@ static int DAC960_Open(Inode_T *Inode, File_T *File) if (ControllerNumber < 0 || ControllerNumber > DAC960_ControllerCount - 1) return -ENXIO; Controller = DAC960_Controllers[ControllerNumber]; - if (Controller == NULL || - LogicalDriveNumber > Controller->LogicalDriveCount - 1) - return -ENXIO; - if (Controller->LogicalDriveInformation - [Controller->LogicalDriveInformationIndex] - [LogicalDriveNumber].LogicalDriveState - == DAC960_LogicalDrive_Offline) - return -ENXIO; - if (Controller->LogicalDriveInitialState[LogicalDriveNumber] - == DAC960_LogicalDrive_Offline) + if (Controller == NULL) return -ENXIO; + if (Controller->FirmwareType == DAC960_V1_Controller) + { + if (LogicalDriveNumber > Controller->LogicalDriveCount - 1) + return -ENXIO; + if (Controller->V1.LogicalDriveInformation + [LogicalDriveNumber].LogicalDriveState + == DAC960_V1_LogicalDrive_Offline) + return -ENXIO; + } + else + { + DAC960_V2_LogicalDeviceInfo_T *LogicalDeviceInfo = + Controller->V2.LogicalDeviceInformation[LogicalDriveNumber]; + if (LogicalDeviceInfo == NULL || + LogicalDeviceInfo->LogicalDeviceState + == DAC960_V2_LogicalDevice_Offline) + return -ENXIO; + } + if (!Controller->LogicalDriveInitiallyAccessible[LogicalDriveNumber]) { - Controller->LogicalDriveInitialState[LogicalDriveNumber] = - DAC960_LogicalDrive_Online; - DAC960_InitializeGenericDiskInfo(&Controller->GenericDiskInfo); + Controller->LogicalDriveInitiallyAccessible[LogicalDriveNumber] = true; + DAC960_RegisterDisk(Controller, LogicalDriveNumber); } if (Controller->GenericDiskInfo.sizes[MINOR(Inode->i_rdev)] == 0) return -ENXIO; @@ -2710,25 +4905,51 @@ static int DAC960_IOCTL(Inode_T *Inode, File_T *File, if (ControllerNumber < 0 || ControllerNumber > DAC960_ControllerCount - 1) return -ENXIO; Controller = DAC960_Controllers[ControllerNumber]; - if (Controller == NULL || - LogicalDriveNumber > Controller->LogicalDriveCount - 1) - return -ENXIO; + if (Controller == NULL) return -ENXIO; switch (Request) { case HDIO_GETGEO: /* Get BIOS Disk Geometry. */ UserGeometry = (DiskGeometry_T *) Argument; if (UserGeometry == NULL) return -EINVAL; - Geometry.heads = Controller->GeometryTranslationHeads; - Geometry.sectors = Controller->GeometryTranslationSectors; - Geometry.cylinders = - Controller->LogicalDriveInformation - [Controller->LogicalDriveInformationIndex] - [LogicalDriveNumber].LogicalDriveSize - / (Controller->GeometryTranslationHeads * - Controller->GeometryTranslationSectors); - Geometry.start = Controller->GenericDiskInfo.part[MINOR(Inode->i_rdev)] - .start_sect; + if (Controller->FirmwareType == DAC960_V1_Controller) + { + if (LogicalDriveNumber > Controller->LogicalDriveCount - 1) + return -ENXIO; + Geometry.heads = Controller->V1.GeometryTranslationHeads; + Geometry.sectors = Controller->V1.GeometryTranslationSectors; + Geometry.cylinders = + Controller->V1.LogicalDriveInformation[LogicalDriveNumber] + .LogicalDriveSize + / (Geometry.heads * Geometry.sectors); + } + else + { + DAC960_V2_LogicalDeviceInfo_T *LogicalDeviceInfo = + Controller->V2.LogicalDeviceInformation[LogicalDriveNumber]; + if (LogicalDeviceInfo == NULL) + return -EINVAL; + switch(LogicalDeviceInfo->DriveGeometry) + { + case DAC960_V2_Geometry_128_32: + Geometry.heads = 128; + Geometry.sectors = 32; + break; + case DAC960_V2_Geometry_255_63: + Geometry.heads = 255; + Geometry.sectors = 63; + break; + default: + DAC960_Error("Illegal Logical Device Geometry %d\n", + Controller, LogicalDeviceInfo->DriveGeometry); + return -EINVAL; + } + Geometry.cylinders = + LogicalDeviceInfo->ConfigurableDeviceSizeIn512ByteBlocksOrMB + / (Geometry.heads * Geometry.sectors); + } + Geometry.start = + Controller->GenericDiskInfo.part[MINOR(Inode->i_rdev)].start_sect; return copy_to_user(UserGeometry, &Geometry, sizeof(DiskGeometry_T)); case BLKGETSIZE: /* Get Device Size. */ @@ -2789,13 +5010,20 @@ static int DAC960_IOCTL(Inode_T *Inode, File_T *File, */ set_blocksize(Device, BLOCK_SIZE); } - /* - * Leonard, I'll tie you, draw around you a pentagram - * and read this file. Aloud. - */ - grok_partitions( - &Controller->GenericDiskInfo, LogicalDriveNumber, DAC960_MaxPartitions, - Controller->LogicalDriveInformation[Controller->LogicalDriveInformationIndex][LogicalDriveNumber].LogicalDriveSize); + if (Controller->FirmwareType == DAC960_V1_Controller) + grok_partitions(&Controller->GenericDiskInfo, + LogicalDriveNumber, + DAC960_MaxPartitions, + Controller->V1.LogicalDriveInformation + [LogicalDriveNumber] + .LogicalDriveSize); + else + grok_partitions( + &Controller->GenericDiskInfo, + LogicalDriveNumber, + DAC960_MaxPartitions, + Controller->V2.LogicalDeviceInformation[LogicalDriveNumber] + ->ConfigurableDeviceSizeIn512ByteBlocksOrMB); return 0; } return -EINVAL; @@ -2830,59 +5058,63 @@ static int DAC960_UserIOCTL(Inode_T *Inode, File_T *File, ControllerNumber > DAC960_ControllerCount - 1) return -ENXIO; Controller = DAC960_Controllers[ControllerNumber]; - if (Controller == NULL) - return -ENXIO; + if (Controller == NULL) return -ENXIO; memset(&ControllerInfo, 0, sizeof(DAC960_ControllerInfo_T)); ControllerInfo.ControllerNumber = ControllerNumber; + ControllerInfo.FirmwareType = Controller->FirmwareType; + ControllerInfo.Channels = Controller->Channels; + ControllerInfo.Targets = Controller->Targets; ControllerInfo.PCI_Bus = Controller->Bus; ControllerInfo.PCI_Device = Controller->Device; ControllerInfo.PCI_Function = Controller->Function; ControllerInfo.IRQ_Channel = Controller->IRQ_Channel; - ControllerInfo.Channels = Controller->Channels; ControllerInfo.PCI_Address = Controller->PCI_Address; strcpy(ControllerInfo.ModelName, Controller->ModelName); strcpy(ControllerInfo.FirmwareVersion, Controller->FirmwareVersion); return copy_to_user(UserSpaceControllerInfo, &ControllerInfo, sizeof(DAC960_ControllerInfo_T)); } - case DAC960_IOCTL_EXECUTE_COMMAND: + case DAC960_IOCTL_V1_EXECUTE_COMMAND: { - DAC960_UserCommand_T *UserSpaceUserCommand = - (DAC960_UserCommand_T *) Argument; - DAC960_UserCommand_T UserCommand; + DAC960_V1_UserCommand_T *UserSpaceUserCommand = + (DAC960_V1_UserCommand_T *) Argument; + DAC960_V1_UserCommand_T UserCommand; DAC960_Controller_T *Controller; DAC960_Command_T *Command = NULL; - DAC960_CommandOpcode_T CommandOpcode; - DAC960_CommandStatus_T CommandStatus; - DAC960_DCDB_T DCDB; + DAC960_V1_CommandOpcode_T CommandOpcode; + DAC960_V1_CommandStatus_T CommandStatus; + DAC960_V1_DCDB_T DCDB; ProcessorFlags_T ProcessorFlags; int ControllerNumber, DataTransferLength; unsigned char *DataTransferBuffer = NULL; if (UserSpaceUserCommand == NULL) return -EINVAL; ErrorCode = copy_from_user(&UserCommand, UserSpaceUserCommand, - sizeof(DAC960_UserCommand_T)); - if (ErrorCode != 0) goto Failure; + sizeof(DAC960_V1_UserCommand_T)); + if (ErrorCode != 0) goto Failure1; ControllerNumber = UserCommand.ControllerNumber; if (ControllerNumber < 0 || ControllerNumber > DAC960_ControllerCount - 1) return -ENXIO; Controller = DAC960_Controllers[ControllerNumber]; - if (Controller == NULL) - return -ENXIO; + if (Controller == NULL) return -ENXIO; + if (Controller->FirmwareType != DAC960_V1_Controller) return -EINVAL; CommandOpcode = UserCommand.CommandMailbox.Common.CommandOpcode; DataTransferLength = UserCommand.DataTransferLength; if (CommandOpcode & 0x80) return -EINVAL; - if (CommandOpcode == DAC960_DCDB) + if (CommandOpcode == DAC960_V1_DCDB) { ErrorCode = - copy_from_user(&DCDB, UserCommand.DCDB, sizeof(DAC960_DCDB_T)); - if (ErrorCode != 0) goto Failure; + copy_from_user(&DCDB, UserCommand.DCDB, sizeof(DAC960_V1_DCDB_T)); + if (ErrorCode != 0) goto Failure1; if (!((DataTransferLength == 0 && - DCDB.Direction == DAC960_DCDB_NoDataTransfer) || + DCDB.Direction + == DAC960_V1_DCDB_NoDataTransfer) || (DataTransferLength > 0 && - DCDB.Direction == DAC960_DCDB_DataTransferDeviceToSystem) || + DCDB.Direction + == DAC960_V1_DCDB_DataTransferDeviceToSystem) || (DataTransferLength < 0 && - DCDB.Direction == DAC960_DCDB_DataTransferSystemToDevice))) + DCDB.Direction + == DAC960_V1_DCDB_DataTransferSystemToDevice))) return -EINVAL; if (((DCDB.TransferLengthHigh4 << 16) | DCDB.TransferLength) != abs(DataTransferLength)) @@ -2901,23 +5133,24 @@ static int DAC960_UserIOCTL(Inode_T *Inode, File_T *File, ErrorCode = copy_from_user(DataTransferBuffer, UserCommand.DataTransferBuffer, -DataTransferLength); - if (ErrorCode != 0) goto Failure; + if (ErrorCode != 0) goto Failure1; } - if (CommandOpcode == DAC960_DCDB) + if (CommandOpcode == DAC960_V1_DCDB) { DAC960_AcquireControllerLock(Controller, &ProcessorFlags); - while (Controller->DirectCommandActive[DCDB.Channel] - [DCDB.TargetID] || + while (Controller->V1.DirectCommandActive[DCDB.Channel] + [DCDB.TargetID] || (Command = DAC960_AllocateCommand(Controller)) == NULL) DAC960_WaitForCommand(Controller); - Controller->DirectCommandActive[DCDB.Channel] - [DCDB.TargetID] = true; + Controller->V1.DirectCommandActive[DCDB.Channel] + [DCDB.TargetID] = true; DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); - DAC960_ClearCommand(Command); + DAC960_V1_ClearCommand(Command); Command->CommandType = DAC960_ImmediateCommand; - memcpy(&Command->CommandMailbox, &UserCommand.CommandMailbox, - sizeof(DAC960_CommandMailbox_T)); - Command->CommandMailbox.Type3.BusAddress = Virtual_to_Bus(&DCDB); + memcpy(&Command->V1.CommandMailbox, &UserCommand.CommandMailbox, + sizeof(DAC960_V1_CommandMailbox_T)); + Command->V1.CommandMailbox.Type3.BusAddress = + Virtual_to_Bus(&DCDB); DCDB.BusAddress = Virtual_to_Bus(DataTransferBuffer); } else @@ -2926,38 +5159,211 @@ static int DAC960_UserIOCTL(Inode_T *Inode, File_T *File, while ((Command = DAC960_AllocateCommand(Controller)) == NULL) DAC960_WaitForCommand(Controller); DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); - DAC960_ClearCommand(Command); + DAC960_V1_ClearCommand(Command); Command->CommandType = DAC960_ImmediateCommand; - memcpy(&Command->CommandMailbox, &UserCommand.CommandMailbox, - sizeof(DAC960_CommandMailbox_T)); + memcpy(&Command->V1.CommandMailbox, &UserCommand.CommandMailbox, + sizeof(DAC960_V1_CommandMailbox_T)); if (DataTransferBuffer != NULL) - Command->CommandMailbox.Type3.BusAddress = + Command->V1.CommandMailbox.Type3.BusAddress = Virtual_to_Bus(DataTransferBuffer); } DAC960_ExecuteCommand(Command); - CommandStatus = Command->CommandStatus; + CommandStatus = Command->V1.CommandStatus; DAC960_AcquireControllerLock(Controller, &ProcessorFlags); DAC960_DeallocateCommand(Command); DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); - if (CommandStatus == DAC960_NormalCompletion && - DataTransferLength > 0) + if (DataTransferLength > 0) { ErrorCode = copy_to_user(UserCommand.DataTransferBuffer, DataTransferBuffer, DataTransferLength); - if (ErrorCode != 0) goto Failure; + if (ErrorCode != 0) goto Failure1; } - if (CommandOpcode == DAC960_DCDB) + if (CommandOpcode == DAC960_V1_DCDB) { - Controller->DirectCommandActive[DCDB.Channel] - [DCDB.TargetID] = false; + Controller->V1.DirectCommandActive[DCDB.Channel] + [DCDB.TargetID] = false; ErrorCode = - copy_to_user(UserCommand.DCDB, &DCDB, sizeof(DAC960_DCDB_T)); - if (ErrorCode != 0) goto Failure; + copy_to_user(UserCommand.DCDB, &DCDB, sizeof(DAC960_V1_DCDB_T)); + if (ErrorCode != 0) goto Failure1; + } + ErrorCode = CommandStatus; + Failure1: + if (DataTransferBuffer != NULL) + kfree(DataTransferBuffer); + return ErrorCode; + } + case DAC960_IOCTL_V2_EXECUTE_COMMAND: + { + DAC960_V2_UserCommand_T *UserSpaceUserCommand = + (DAC960_V2_UserCommand_T *) Argument; + DAC960_V2_UserCommand_T UserCommand; + DAC960_Controller_T *Controller; + DAC960_Command_T *Command = NULL; + DAC960_V2_CommandMailbox_T *CommandMailbox; + DAC960_V2_CommandStatus_T CommandStatus; + ProcessorFlags_T ProcessorFlags; + int ControllerNumber, DataTransferLength; + int DataTransferResidue, RequestSenseLength; + unsigned char *DataTransferBuffer = NULL; + unsigned char *RequestSenseBuffer = NULL; + if (UserSpaceUserCommand == NULL) return -EINVAL; + ErrorCode = copy_from_user(&UserCommand, UserSpaceUserCommand, + sizeof(DAC960_V2_UserCommand_T)); + if (ErrorCode != 0) goto Failure2; + ControllerNumber = UserCommand.ControllerNumber; + if (ControllerNumber < 0 || + ControllerNumber > DAC960_ControllerCount - 1) + return -ENXIO; + Controller = DAC960_Controllers[ControllerNumber]; + if (Controller == NULL) return -ENXIO; + if (Controller->FirmwareType != DAC960_V2_Controller) return -EINVAL; + DataTransferLength = UserCommand.DataTransferLength; + if (DataTransferLength > 0) + { + DataTransferBuffer = kmalloc(DataTransferLength, GFP_KERNEL); + if (DataTransferBuffer == NULL) return -ENOMEM; + memset(DataTransferBuffer, 0, DataTransferLength); + } + else if (DataTransferLength < 0) + { + DataTransferBuffer = kmalloc(-DataTransferLength, GFP_KERNEL); + if (DataTransferBuffer == NULL) return -ENOMEM; + ErrorCode = copy_from_user(DataTransferBuffer, + UserCommand.DataTransferBuffer, + -DataTransferLength); + if (ErrorCode != 0) goto Failure2; + } + RequestSenseLength = UserCommand.RequestSenseLength; + if (RequestSenseLength > 0) + { + RequestSenseBuffer = kmalloc(RequestSenseLength, GFP_KERNEL); + if (RequestSenseBuffer == NULL) + { + ErrorCode = -ENOMEM; + goto Failure2; + } + memset(RequestSenseBuffer, 0, RequestSenseLength); + } + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + while ((Command = DAC960_AllocateCommand(Controller)) == NULL) + DAC960_WaitForCommand(Controller); + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + DAC960_V2_ClearCommand(Command); + Command->CommandType = DAC960_ImmediateCommand; + CommandMailbox = &Command->V2.CommandMailbox; + memcpy(CommandMailbox, &UserCommand.CommandMailbox, + sizeof(DAC960_V2_CommandMailbox_T)); + CommandMailbox->Common.CommandControlBits + .AdditionalScatterGatherListMemory = false; + CommandMailbox->Common.CommandControlBits + .NoAutoRequestSense = true; + CommandMailbox->Common.DataTransferSize = 0; + CommandMailbox->Common.DataTransferPageNumber = 0; + memset(&CommandMailbox->Common.DataTransferMemoryAddress, 0, + sizeof(DAC960_V2_DataTransferMemoryAddress_T)); + if (DataTransferLength != 0) + { + if (DataTransferLength > 0) + { + CommandMailbox->Common.CommandControlBits + .DataTransferControllerToHost = true; + CommandMailbox->Common.DataTransferSize = DataTransferLength; + } + else + { + CommandMailbox->Common.CommandControlBits + .DataTransferControllerToHost = false; + CommandMailbox->Common.DataTransferSize = -DataTransferLength; + } + CommandMailbox->Common.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Virtual_to_Bus(DataTransferBuffer); + CommandMailbox->Common.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->Common.DataTransferSize; + } + if (RequestSenseLength > 0) + { + CommandMailbox->Common.CommandControlBits + .NoAutoRequestSense = false; + CommandMailbox->Common.RequestSenseSize = RequestSenseLength; + CommandMailbox->Common.RequestSenseBusAddress = + Virtual_to_Bus(RequestSenseBuffer); + } + DAC960_ExecuteCommand(Command); + CommandStatus = Command->V2.CommandStatus; + RequestSenseLength = Command->V2.RequestSenseLength; + DataTransferResidue = Command->V2.DataTransferResidue; + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + DAC960_DeallocateCommand(Command); + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + if (RequestSenseLength > UserCommand.RequestSenseLength) + RequestSenseLength = UserCommand.RequestSenseLength; + ErrorCode = copy_to_user(&UserSpaceUserCommand->DataTransferLength, + &DataTransferResidue, + sizeof(DataTransferResidue)); + if (ErrorCode != 0) goto Failure2; + ErrorCode = copy_to_user(&UserSpaceUserCommand->RequestSenseLength, + &RequestSenseLength, + sizeof(RequestSenseLength)); + if (ErrorCode != 0) goto Failure2; + if (DataTransferLength > 0) + { + ErrorCode = copy_to_user(UserCommand.DataTransferBuffer, + DataTransferBuffer, DataTransferLength); + if (ErrorCode != 0) goto Failure2; + } + if (RequestSenseLength > 0) + { + ErrorCode = copy_to_user(UserCommand.RequestSenseBuffer, + RequestSenseBuffer, RequestSenseLength); + if (ErrorCode != 0) goto Failure2; } ErrorCode = CommandStatus; - Failure: + Failure2: if (DataTransferBuffer != NULL) kfree(DataTransferBuffer); + if (RequestSenseBuffer != NULL) + kfree(RequestSenseBuffer); + return ErrorCode; + } + case DAC960_IOCTL_V2_GET_HEALTH_STATUS: + { + DAC960_V2_GetHealthStatus_T *UserSpaceGetHealthStatus = + (DAC960_V2_GetHealthStatus_T *) Argument; + DAC960_V2_GetHealthStatus_T GetHealthStatus; + DAC960_V2_HealthStatusBuffer_T HealthStatusBuffer; + DAC960_Controller_T *Controller; + int ControllerNumber; + if (UserSpaceGetHealthStatus == NULL) return -EINVAL; + ErrorCode = copy_from_user(&GetHealthStatus, UserSpaceGetHealthStatus, + sizeof(DAC960_V2_GetHealthStatus_T)); + if (ErrorCode != 0) return ErrorCode; + ControllerNumber = GetHealthStatus.ControllerNumber; + if (ControllerNumber < 0 || + ControllerNumber > DAC960_ControllerCount - 1) + return -ENXIO; + Controller = DAC960_Controllers[ControllerNumber]; + if (Controller == NULL) return -ENXIO; + if (Controller->FirmwareType != DAC960_V2_Controller) return -EINVAL; + ErrorCode = copy_from_user(&HealthStatusBuffer, + GetHealthStatus.HealthStatusBuffer, + sizeof(DAC960_V2_HealthStatusBuffer_T)); + if (ErrorCode != 0) return ErrorCode; + while (Controller->V2.HealthStatusBuffer->StatusChangeCounter + == HealthStatusBuffer.StatusChangeCounter && + Controller->V2.HealthStatusBuffer->NextEventSequenceNumber + == HealthStatusBuffer.NextEventSequenceNumber) + { + interruptible_sleep_on_timeout(&Controller->HealthStatusWaitQueue, + DAC960_MonitoringTimerInterval); + if (signal_pending(current)) return -EINTR; + } + ErrorCode = copy_to_user(GetHealthStatus.HealthStatusBuffer, + Controller->V2.HealthStatusBuffer, + sizeof(DAC960_V2_HealthStatusBuffer_T)); return ErrorCode; } } @@ -2987,28 +5393,29 @@ int DAC960_KernelIOCTL(unsigned int Request, void *Argument) ControllerNumber > DAC960_ControllerCount - 1) return -ENXIO; Controller = DAC960_Controllers[ControllerNumber]; - if (Controller == NULL) - return -ENXIO; + if (Controller == NULL) return -ENXIO; memset(ControllerInfo, 0, sizeof(DAC960_ControllerInfo_T)); ControllerInfo->ControllerNumber = ControllerNumber; + ControllerInfo->FirmwareType = Controller->FirmwareType; + ControllerInfo->Channels = Controller->Channels; + ControllerInfo->Targets = Controller->Targets; ControllerInfo->PCI_Bus = Controller->Bus; ControllerInfo->PCI_Device = Controller->Device; ControllerInfo->PCI_Function = Controller->Function; ControllerInfo->IRQ_Channel = Controller->IRQ_Channel; - ControllerInfo->Channels = Controller->Channels; ControllerInfo->PCI_Address = Controller->PCI_Address; strcpy(ControllerInfo->ModelName, Controller->ModelName); strcpy(ControllerInfo->FirmwareVersion, Controller->FirmwareVersion); return 0; } - case DAC960_IOCTL_EXECUTE_COMMAND: + case DAC960_IOCTL_V1_EXECUTE_COMMAND: { - DAC960_KernelCommand_T *KernelCommand = - (DAC960_KernelCommand_T *) Argument; + DAC960_V1_KernelCommand_T *KernelCommand = + (DAC960_V1_KernelCommand_T *) Argument; DAC960_Controller_T *Controller; DAC960_Command_T *Command = NULL; - DAC960_CommandOpcode_T CommandOpcode; - DAC960_DCDB_T *DCDB = NULL; + DAC960_V1_CommandOpcode_T CommandOpcode; + DAC960_V1_DCDB_T *DCDB = NULL; ProcessorFlags_T ProcessorFlags; int ControllerNumber, DataTransferLength; unsigned char *DataTransferBuffer = NULL; @@ -3018,21 +5425,23 @@ int DAC960_KernelIOCTL(unsigned int Request, void *Argument) ControllerNumber > DAC960_ControllerCount - 1) return -ENXIO; Controller = DAC960_Controllers[ControllerNumber]; - if (Controller == NULL) - return -ENXIO; + if (Controller == NULL) return -ENXIO; + if (Controller->FirmwareType != DAC960_V1_Controller) return -EINVAL; CommandOpcode = KernelCommand->CommandMailbox.Common.CommandOpcode; DataTransferLength = KernelCommand->DataTransferLength; DataTransferBuffer = KernelCommand->DataTransferBuffer; if (CommandOpcode & 0x80) return -EINVAL; - if (CommandOpcode == DAC960_DCDB) + if (CommandOpcode == DAC960_V1_DCDB) { DCDB = KernelCommand->DCDB; if (!((DataTransferLength == 0 && - DCDB->Direction == DAC960_DCDB_NoDataTransfer) || + DCDB->Direction == DAC960_V1_DCDB_NoDataTransfer) || (DataTransferLength > 0 && - DCDB->Direction == DAC960_DCDB_DataTransferDeviceToSystem) || + DCDB->Direction + == DAC960_V1_DCDB_DataTransferDeviceToSystem) || (DataTransferLength < 0 && - DCDB->Direction == DAC960_DCDB_DataTransferSystemToDevice))) + DCDB->Direction + == DAC960_V1_DCDB_DataTransferSystemToDevice))) return -EINVAL; if (((DCDB->TransferLengthHigh4 << 16) | DCDB->TransferLength) != abs(DataTransferLength)) @@ -3042,25 +5451,26 @@ int DAC960_KernelIOCTL(unsigned int Request, void *Argument) return -EINVAL; if (DataTransferLength > 0) memset(DataTransferBuffer, 0, DataTransferLength); - if (CommandOpcode == DAC960_DCDB) + if (CommandOpcode == DAC960_V1_DCDB) { DAC960_AcquireControllerLock(Controller, &ProcessorFlags); - if (!Controller->DirectCommandActive[DCDB->Channel] - [DCDB->TargetID]) + if (!Controller->V1.DirectCommandActive[DCDB->Channel] + [DCDB->TargetID]) Command = DAC960_AllocateCommand(Controller); if (Command == NULL) { DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); return -EBUSY; } - else Controller->DirectCommandActive[DCDB->Channel] - [DCDB->TargetID] = true; - DAC960_ClearCommand(Command); + else Controller->V1.DirectCommandActive[DCDB->Channel] + [DCDB->TargetID] = true; + DAC960_V1_ClearCommand(Command); Command->CommandType = DAC960_QueuedCommand; - memcpy(&Command->CommandMailbox, &KernelCommand->CommandMailbox, - sizeof(DAC960_CommandMailbox_T)); - Command->CommandMailbox.Type3.BusAddress = Virtual_to_Bus(DCDB); - Command->KernelCommand = KernelCommand; + memcpy(&Command->V1.CommandMailbox, &KernelCommand->CommandMailbox, + sizeof(DAC960_V1_CommandMailbox_T)); + Command->V1.CommandMailbox.Type3.BusAddress = + Virtual_to_Bus(DCDB); + Command->V1.KernelCommand = KernelCommand; DCDB->BusAddress = Virtual_to_Bus(DataTransferBuffer); DAC960_QueueCommand(Command); DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); @@ -3074,44 +5484,153 @@ int DAC960_KernelIOCTL(unsigned int Request, void *Argument) DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); return -EBUSY; } - DAC960_ClearCommand(Command); + DAC960_V1_ClearCommand(Command); Command->CommandType = DAC960_QueuedCommand; - memcpy(&Command->CommandMailbox, &KernelCommand->CommandMailbox, - sizeof(DAC960_CommandMailbox_T)); + memcpy(&Command->V1.CommandMailbox, &KernelCommand->CommandMailbox, + sizeof(DAC960_V1_CommandMailbox_T)); if (DataTransferBuffer != NULL) - Command->CommandMailbox.Type3.BusAddress = + Command->V1.CommandMailbox.Type3.BusAddress = Virtual_to_Bus(DataTransferBuffer); - Command->KernelCommand = KernelCommand; + Command->V1.KernelCommand = KernelCommand; DAC960_QueueCommand(Command); DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); } return 0; } + case DAC960_IOCTL_V2_EXECUTE_COMMAND: + { + DAC960_V2_KernelCommand_T *KernelCommand = + (DAC960_V2_KernelCommand_T *) Argument; + DAC960_Controller_T *Controller; + DAC960_Command_T *Command = NULL; + DAC960_V2_CommandMailbox_T *CommandMailbox; + ProcessorFlags_T ProcessorFlags; + int ControllerNumber, DataTransferLength, RequestSenseLength; + unsigned char *DataTransferBuffer = NULL; + unsigned char *RequestSenseBuffer = NULL; + if (KernelCommand == NULL) return -EINVAL; + ControllerNumber = KernelCommand->ControllerNumber; + if (ControllerNumber < 0 || + ControllerNumber > DAC960_ControllerCount - 1) + return -ENXIO; + Controller = DAC960_Controllers[ControllerNumber]; + if (Controller == NULL) return -ENXIO; + if (Controller->FirmwareType != DAC960_V2_Controller) return -EINVAL; + DataTransferLength = KernelCommand->DataTransferLength; + RequestSenseLength = KernelCommand->RequestSenseLength; + DataTransferBuffer = KernelCommand->DataTransferBuffer; + RequestSenseBuffer = KernelCommand->RequestSenseBuffer; + if (DataTransferLength != 0 && DataTransferBuffer == NULL) + return -EINVAL; + if (RequestSenseLength < 0) + return -EINVAL; + if (RequestSenseLength > 0 && RequestSenseBuffer == NULL) + return -EINVAL; + if (DataTransferLength > 0) + memset(DataTransferBuffer, 0, DataTransferLength); + if (RequestSenseLength > 0) + memset(RequestSenseBuffer, 0, RequestSenseLength); + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + Command = DAC960_AllocateCommand(Controller); + if (Command == NULL) + { + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + return -EBUSY; + } + DAC960_V2_ClearCommand(Command); + Command->CommandType = DAC960_QueuedCommand; + CommandMailbox = &Command->V2.CommandMailbox; + memcpy(CommandMailbox, &KernelCommand->CommandMailbox, + sizeof(DAC960_V2_CommandMailbox_T)); + CommandMailbox->Common.CommandControlBits + .AdditionalScatterGatherListMemory = false; + CommandMailbox->Common.CommandControlBits + .NoAutoRequestSense = true; + CommandMailbox->Common.DataTransferSize = 0; + CommandMailbox->Common.DataTransferPageNumber = 0; + memset(&CommandMailbox->Common.DataTransferMemoryAddress, 0, + sizeof(DAC960_V2_DataTransferMemoryAddress_T)); + if (DataTransferLength != 0) + { + if (DataTransferLength > 0) + { + CommandMailbox->Common.CommandControlBits + .DataTransferControllerToHost = true; + CommandMailbox->Common.DataTransferSize = DataTransferLength; + } + else + { + CommandMailbox->Common.CommandControlBits + .DataTransferControllerToHost = false; + CommandMailbox->Common.DataTransferSize = -DataTransferLength; + } + CommandMailbox->Common.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Virtual_to_Bus(DataTransferBuffer); + CommandMailbox->Common.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->Common.DataTransferSize; + } + if (RequestSenseLength > 0) + { + CommandMailbox->Common.CommandControlBits + .NoAutoRequestSense = false; + CommandMailbox->Common.RequestSenseBusAddress = + Virtual_to_Bus(RequestSenseBuffer); + } + Command->V2.KernelCommand = KernelCommand; + DAC960_QueueCommand(Command); + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + return 0; + } } return -EINVAL; } /* - DAC960_GenericDiskInit is the Generic Disk Information Initialization - Function for the DAC960 Driver. + DAC960_CheckStatusBuffer verifies that there is room to hold ByteCount + additional bytes in the Combined Status Buffer and grows the buffer if + necessary. It returns true if there is enough room and false otherwise. */ -static void DAC960_InitializeGenericDiskInfo(GenericDiskInfo_T *GenericDiskInfo) +static boolean DAC960_CheckStatusBuffer(DAC960_Controller_T *Controller, + unsigned int ByteCount) { - DAC960_Controller_T *Controller = - (DAC960_Controller_T *) GenericDiskInfo->real_devices; - DAC960_LogicalDriveInformation_T *LogicalDriveInformation = - Controller->LogicalDriveInformation - [Controller->LogicalDriveInformationIndex]; - int LogicalDriveNumber; - for (LogicalDriveNumber = 0; - LogicalDriveNumber < Controller->LogicalDriveCount; - LogicalDriveNumber++) - register_disk(GenericDiskInfo, MKDEV(GenericDiskInfo->major, - LogicalDriveNumber*DAC960_MaxPartitions), - DAC960_MaxPartitions, &DAC960_FileOperations, - LogicalDriveInformation[LogicalDriveNumber].LogicalDriveSize); + unsigned char *NewStatusBuffer; + if (Controller->InitialStatusLength + 1 + + Controller->CurrentStatusLength + ByteCount + 1 <= + Controller->CombinedStatusBufferLength) + return true; + if (Controller->CombinedStatusBufferLength == 0) + { + unsigned int NewStatusBufferLength = DAC960_InitialStatusBufferSize; + while (NewStatusBufferLength < ByteCount) + NewStatusBufferLength *= 2; + Controller->CombinedStatusBuffer = + (unsigned char *) kmalloc(NewStatusBufferLength, GFP_ATOMIC); + if (Controller->CombinedStatusBuffer == NULL) return false; + Controller->CombinedStatusBufferLength = NewStatusBufferLength; + return true; + } + NewStatusBuffer = (unsigned char *) + kmalloc(2 * Controller->CombinedStatusBufferLength, GFP_ATOMIC); + if (NewStatusBuffer == NULL) + { + DAC960_Warning("Unable to expand Combined Status Buffer - Truncating\n", + Controller); + return false; + } + memcpy(NewStatusBuffer, Controller->CombinedStatusBuffer, + Controller->CombinedStatusBufferLength); + kfree(Controller->CombinedStatusBuffer); + Controller->CombinedStatusBuffer = NewStatusBuffer; + Controller->CombinedStatusBufferLength *= 2; + Controller->CurrentStatusBuffer = + &NewStatusBuffer[Controller->InitialStatusLength + 1]; + return true; } @@ -3120,11 +5639,11 @@ static void DAC960_InitializeGenericDiskInfo(GenericDiskInfo_T *GenericDiskInfo) */ static void DAC960_Message(DAC960_MessageLevel_T MessageLevel, - char *Format, + unsigned char *Format, DAC960_Controller_T *Controller, ...) { - static char Buffer[DAC960_LineBufferSize]; + static unsigned char Buffer[DAC960_LineBufferSize]; static boolean BeginningOfLine = true; va_list Arguments; int Length = 0; @@ -3139,9 +5658,16 @@ static void DAC960_Message(DAC960_MessageLevel_T MessageLevel, { if (!Controller->ControllerInitialized) { - strcpy(&Controller->InitialStatusBuffer[ - Controller->InitialStatusLength], Buffer); - Controller->InitialStatusLength += Length; + if (DAC960_CheckStatusBuffer(Controller, Length)) + { + strcpy(&Controller->CombinedStatusBuffer + [Controller->InitialStatusLength], + Buffer); + Controller->InitialStatusLength += Length; + Controller->CurrentStatusBuffer = + &Controller->CombinedStatusBuffer + [Controller->InitialStatusLength + 1]; + } if (MessageLevel == DAC960_AnnounceLevel) { static int AnnouncementLines = 0; @@ -3161,7 +5687,7 @@ static void DAC960_Message(DAC960_MessageLevel_T MessageLevel, else printk("%s", Buffer); } } - else + else if (DAC960_CheckStatusBuffer(Controller, Length)) { strcpy(&Controller->CurrentStatusBuffer[ Controller->CurrentStatusLength], Buffer); @@ -3170,8 +5696,8 @@ static void DAC960_Message(DAC960_MessageLevel_T MessageLevel, } else if (MessageLevel == DAC960_ProgressLevel) { - strcpy(Controller->RebuildProgressBuffer, Buffer); - Controller->RebuildProgressLength = Length; + strcpy(Controller->ProgressBuffer, Buffer); + Controller->ProgressBufferLength = Length; if (Controller->EphemeralProgressMessage) { if (jiffies - Controller->LastProgressReportTime @@ -3206,15 +5732,15 @@ static void DAC960_Message(DAC960_MessageLevel_T MessageLevel, /* - DAC960_ParsePhysicalDrive parses spaces followed by a Physical Drive + DAC960_ParsePhysicalDevice parses spaces followed by a Physical Device Channel:TargetID specification from a User Command string. It updates - Channel and TargetID and returns true on success and returns false otherwise. + Channel and TargetID and returns true on success and false on failure. */ -static boolean DAC960_ParsePhysicalDrive(DAC960_Controller_T *Controller, - char *UserCommandString, - unsigned char *Channel, - unsigned char *TargetID) +static boolean DAC960_ParsePhysicalDevice(DAC960_Controller_T *Controller, + char *UserCommandString, + unsigned char *Channel, + unsigned char *TargetID) { char *NewUserCommandString = UserCommandString; unsigned long XChannel, XTargetID; @@ -3230,7 +5756,7 @@ static boolean DAC960_ParsePhysicalDrive(DAC960_Controller_T *Controller, XTargetID = simple_strtoul(UserCommandString, &NewUserCommandString, 10); if (NewUserCommandString == UserCommandString || *NewUserCommandString != '\0' || - XTargetID >= DAC960_MaxTargets) + XTargetID >= Controller->Targets) return false; *Channel = XChannel; *TargetID = XTargetID; @@ -3241,7 +5767,7 @@ static boolean DAC960_ParsePhysicalDrive(DAC960_Controller_T *Controller, /* DAC960_ParseLogicalDrive parses spaces followed by a Logical Drive Number specification from a User Command string. It updates LogicalDriveNumber and - returns true on success and returns false otherwise. + returns true on success and false on failure. */ static boolean DAC960_ParseLogicalDrive(DAC960_Controller_T *Controller, @@ -3257,7 +5783,7 @@ static boolean DAC960_ParseLogicalDrive(DAC960_Controller_T *Controller, simple_strtoul(UserCommandString, &NewUserCommandString, 10); if (NewUserCommandString == UserCommandString || *NewUserCommandString != '\0' || - XLogicalDriveNumber >= Controller->LogicalDriveCount) + XLogicalDriveNumber > DAC960_MaxLogicalDrives - 1) return false; *LogicalDriveNumber = XLogicalDriveNumber; return true; @@ -3265,68 +5791,71 @@ static boolean DAC960_ParseLogicalDrive(DAC960_Controller_T *Controller, /* - DAC960_SetDeviceState sets the Device State for a Physical Drive. + DAC960_V1_SetDeviceState sets the Device State for a Physical Device for + DAC960 V1 Firmware Controllers. */ -static void DAC960_SetDeviceState(DAC960_Controller_T *Controller, - DAC960_Command_T *Command, - unsigned char Channel, - unsigned char TargetID, - DAC960_PhysicalDeviceState_T DeviceState, - const char *DeviceStateString) +static void DAC960_V1_SetDeviceState(DAC960_Controller_T *Controller, + DAC960_Command_T *Command, + unsigned char Channel, + unsigned char TargetID, + DAC960_V1_PhysicalDeviceState_T + DeviceState, + const unsigned char *DeviceStateString) { - DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; - CommandMailbox->Type3D.CommandOpcode = DAC960_StartDevice; + DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; + CommandMailbox->Type3D.CommandOpcode = DAC960_V1_StartDevice; CommandMailbox->Type3D.Channel = Channel; CommandMailbox->Type3D.TargetID = TargetID; CommandMailbox->Type3D.DeviceState = DeviceState; CommandMailbox->Type3D.Modifier = 0; DAC960_ExecuteCommand(Command); - switch (Command->CommandStatus) + switch (Command->V1.CommandStatus) { - case DAC960_NormalCompletion: - DAC960_UserCritical("%s of Physical Drive %d:%d Succeeded\n", Controller, + case DAC960_V1_NormalCompletion: + DAC960_UserCritical("%s of Physical Device %d:%d Succeeded\n", Controller, DeviceStateString, Channel, TargetID); break; - case DAC960_UnableToStartDevice: - DAC960_UserCritical("%s of Physical Drive %d:%d Failed - " + case DAC960_V1_UnableToStartDevice: + DAC960_UserCritical("%s of Physical Device %d:%d Failed - " "Unable to Start Device\n", Controller, DeviceStateString, Channel, TargetID); break; - case DAC960_NoDeviceAtAddress: - DAC960_UserCritical("%s of Physical Drive %d:%d Failed - " + case DAC960_V1_NoDeviceAtAddress: + DAC960_UserCritical("%s of Physical Device %d:%d Failed - " "No Device at Address\n", Controller, DeviceStateString, Channel, TargetID); break; - case DAC960_InvalidChannelOrTargetOrModifier: - DAC960_UserCritical("%s of Physical Drive %d:%d Failed - " + case DAC960_V1_InvalidChannelOrTargetOrModifier: + DAC960_UserCritical("%s of Physical Device %d:%d Failed - " "Invalid Channel or Target or Modifier\n", Controller, DeviceStateString, Channel, TargetID); break; - case DAC960_ChannelBusy: - DAC960_UserCritical("%s of Physical Drive %d:%d Failed - " + case DAC960_V1_ChannelBusy: + DAC960_UserCritical("%s of Physical Device %d:%d Failed - " "Channel Busy\n", Controller, DeviceStateString, Channel, TargetID); break; default: - DAC960_UserCritical("%s of Physical Drive %d:%d Failed - " + DAC960_UserCritical("%s of Physical Device %d:%d Failed - " "Unexpected Status %04X\n", Controller, DeviceStateString, Channel, TargetID, - Command->CommandStatus); + Command->V1.CommandStatus); break; } } /* - DAC960_ExecuteUserCommand executes a User Command. + DAC960_V1_ExecuteUserCommand executes a User Command for DAC960 V1 Firmware + Controllers. */ -static boolean DAC960_ExecuteUserCommand(DAC960_Controller_T *Controller, - char *UserCommand) +static boolean DAC960_V1_ExecuteUserCommand(DAC960_Controller_T *Controller, + unsigned char *UserCommand) { DAC960_Command_T *Command; - DAC960_CommandMailbox_T *CommandMailbox; + DAC960_V1_CommandMailbox_T *CommandMailbox; ProcessorFlags_T ProcessorFlags; unsigned char Channel, TargetID, LogicalDriveNumber; DAC960_AcquireControllerLock(Controller, &ProcessorFlags); @@ -3334,100 +5863,98 @@ static boolean DAC960_ExecuteUserCommand(DAC960_Controller_T *Controller, DAC960_WaitForCommand(Controller); DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); Controller->UserStatusLength = 0; - DAC960_ClearCommand(Command); + DAC960_V1_ClearCommand(Command); Command->CommandType = DAC960_ImmediateCommand; - CommandMailbox = &Command->CommandMailbox; + CommandMailbox = &Command->V1.CommandMailbox; if (strcmp(UserCommand, "flush-cache") == 0) { - CommandMailbox->Type3.CommandOpcode = DAC960_Flush; + CommandMailbox->Type3.CommandOpcode = DAC960_V1_Flush; DAC960_ExecuteCommand(Command); DAC960_UserCritical("Cache Flush Completed\n", Controller); } else if (strncmp(UserCommand, "kill", 4) == 0 && - DAC960_ParsePhysicalDrive(Controller, &UserCommand[4], - &Channel, &TargetID)) + DAC960_ParsePhysicalDevice(Controller, &UserCommand[4], + &Channel, &TargetID)) { - DAC960_DeviceState_T *DeviceState = - &Controller->DeviceState[Controller->DeviceStateIndex] - [Channel][TargetID]; + DAC960_V1_DeviceState_T *DeviceState = + &Controller->V1.DeviceState[Channel][TargetID]; if (DeviceState->Present && - DeviceState->DeviceType == DAC960_DiskType && - DeviceState->DeviceState != DAC960_Device_Dead) - DAC960_SetDeviceState(Controller, Command, Channel, TargetID, - DAC960_Device_Dead, "Kill"); - else DAC960_UserCritical("Kill of Physical Drive %d:%d Illegal\n", + DeviceState->DeviceType == DAC960_V1_DiskType && + DeviceState->DeviceState != DAC960_V1_Device_Dead) + DAC960_V1_SetDeviceState(Controller, Command, Channel, TargetID, + DAC960_V1_Device_Dead, "Kill"); + else DAC960_UserCritical("Kill of Physical Device %d:%d Illegal\n", Controller, Channel, TargetID); } else if (strncmp(UserCommand, "make-online", 11) == 0 && - DAC960_ParsePhysicalDrive(Controller, &UserCommand[11], - &Channel, &TargetID)) + DAC960_ParsePhysicalDevice(Controller, &UserCommand[11], + &Channel, &TargetID)) { - DAC960_DeviceState_T *DeviceState = - &Controller->DeviceState[Controller->DeviceStateIndex] - [Channel][TargetID]; + DAC960_V1_DeviceState_T *DeviceState = + &Controller->V1.DeviceState[Channel][TargetID]; if (DeviceState->Present && - DeviceState->DeviceType == DAC960_DiskType && - DeviceState->DeviceState == DAC960_Device_Dead) - DAC960_SetDeviceState(Controller, Command, Channel, TargetID, - DAC960_Device_Online, "Make Online"); - else DAC960_UserCritical("Make Online of Physical Drive %d:%d Illegal\n", + DeviceState->DeviceType == DAC960_V1_DiskType && + DeviceState->DeviceState == DAC960_V1_Device_Dead) + DAC960_V1_SetDeviceState(Controller, Command, Channel, TargetID, + DAC960_V1_Device_Online, "Make Online"); + else DAC960_UserCritical("Make Online of Physical Device %d:%d Illegal\n", Controller, Channel, TargetID); } else if (strncmp(UserCommand, "make-standby", 12) == 0 && - DAC960_ParsePhysicalDrive(Controller, &UserCommand[12], - &Channel, &TargetID)) + DAC960_ParsePhysicalDevice(Controller, &UserCommand[12], + &Channel, &TargetID)) { - DAC960_DeviceState_T *DeviceState = - &Controller->DeviceState[Controller->DeviceStateIndex] - [Channel][TargetID]; + DAC960_V1_DeviceState_T *DeviceState = + &Controller->V1.DeviceState[Channel][TargetID]; if (DeviceState->Present && - DeviceState->DeviceType == DAC960_DiskType && - DeviceState->DeviceState == DAC960_Device_Dead) - DAC960_SetDeviceState(Controller, Command, Channel, TargetID, - DAC960_Device_Standby, "Make Standby"); - else DAC960_UserCritical("Make Standby of Physical Drive %d:%d Illegal\n", + DeviceState->DeviceType == DAC960_V1_DiskType && + DeviceState->DeviceState == DAC960_V1_Device_Dead) + DAC960_V1_SetDeviceState(Controller, Command, Channel, TargetID, + DAC960_V1_Device_Standby, "Make Standby"); + else DAC960_UserCritical("Make Standby of Physical " + "Device %d:%d Illegal\n", Controller, Channel, TargetID); } else if (strncmp(UserCommand, "rebuild", 7) == 0 && - DAC960_ParsePhysicalDrive(Controller, &UserCommand[7], - &Channel, &TargetID)) + DAC960_ParsePhysicalDevice(Controller, &UserCommand[7], + &Channel, &TargetID)) { - CommandMailbox->Type3D.CommandOpcode = DAC960_RebuildAsync; + CommandMailbox->Type3D.CommandOpcode = DAC960_V1_RebuildAsync; CommandMailbox->Type3D.Channel = Channel; CommandMailbox->Type3D.TargetID = TargetID; DAC960_ExecuteCommand(Command); - switch (Command->CommandStatus) + switch (Command->V1.CommandStatus) { - case DAC960_NormalCompletion: - DAC960_UserCritical("Rebuild of Physical Drive %d:%d Initiated\n", + case DAC960_V1_NormalCompletion: + DAC960_UserCritical("Rebuild of Physical Device %d:%d Initiated\n", Controller, Channel, TargetID); break; - case DAC960_AttemptToRebuildOnlineDrive: - DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - " + case DAC960_V1_AttemptToRebuildOnlineDrive: + DAC960_UserCritical("Rebuild of Physical Device %d:%d Failed - " "Attempt to Rebuild Online or " "Unresponsive Drive\n", Controller, Channel, TargetID); break; - case DAC960_NewDiskFailedDuringRebuild: - DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - " + case DAC960_V1_NewDiskFailedDuringRebuild: + DAC960_UserCritical("Rebuild of Physical Device %d:%d Failed - " "New Disk Failed During Rebuild\n", Controller, Channel, TargetID); break; - case DAC960_InvalidDeviceAddress: - DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - " + case DAC960_V1_InvalidDeviceAddress: + DAC960_UserCritical("Rebuild of Physical Device %d:%d Failed - " "Invalid Device Address\n", Controller, Channel, TargetID); break; - case DAC960_RebuildOrCheckAlreadyInProgress: - DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - " + case DAC960_V1_RebuildOrCheckAlreadyInProgress: + DAC960_UserCritical("Rebuild of Physical Device %d:%d Failed - " "Rebuild or Consistency Check Already " "in Progress\n", Controller, Channel, TargetID); break; default: - DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - " + DAC960_UserCritical("Rebuild of Physical Device %d:%d Failed - " "Unexpected Status %04X\n", Controller, - Channel, TargetID, Command->CommandStatus); + Channel, TargetID, Command->V1.CommandStatus); break; } } @@ -3435,28 +5962,28 @@ static boolean DAC960_ExecuteUserCommand(DAC960_Controller_T *Controller, DAC960_ParseLogicalDrive(Controller, &UserCommand[17], &LogicalDriveNumber)) { - CommandMailbox->Type3C.CommandOpcode = DAC960_CheckConsistencyAsync; + CommandMailbox->Type3C.CommandOpcode = DAC960_V1_CheckConsistencyAsync; CommandMailbox->Type3C.LogicalDriveNumber = LogicalDriveNumber; CommandMailbox->Type3C.AutoRestore = true; DAC960_ExecuteCommand(Command); - switch (Command->CommandStatus) + switch (Command->V1.CommandStatus) { - case DAC960_NormalCompletion: + case DAC960_V1_NormalCompletion: DAC960_UserCritical("Consistency Check of Logical Drive %d " "(/dev/rd/c%dd%d) Initiated\n", Controller, LogicalDriveNumber, Controller->ControllerNumber, LogicalDriveNumber); break; - case DAC960_DependentDiskIsDead: + case DAC960_V1_DependentDiskIsDead: DAC960_UserCritical("Consistency Check of Logical Drive %d " "(/dev/rd/c%dd%d) Failed - " - "Dependent Physical Drive is DEAD\n", + "Dependent Physical Device is DEAD\n", Controller, LogicalDriveNumber, Controller->ControllerNumber, LogicalDriveNumber); break; - case DAC960_InvalidOrNonredundantLogicalDrive: + case DAC960_V1_InvalidOrNonredundantLogicalDrive: DAC960_UserCritical("Consistency Check of Logical Drive %d " "(/dev/rd/c%dd%d) Failed - " "Invalid or Nonredundant Logical Drive\n", @@ -3464,7 +5991,7 @@ static boolean DAC960_ExecuteUserCommand(DAC960_Controller_T *Controller, Controller->ControllerNumber, LogicalDriveNumber); break; - case DAC960_RebuildOrCheckAlreadyInProgress: + case DAC960_V1_RebuildOrCheckAlreadyInProgress: DAC960_UserCritical("Consistency Check of Logical Drive %d " "(/dev/rd/c%dd%d) Failed - Rebuild or " "Consistency Check Already in Progress\n", @@ -3478,7 +6005,7 @@ static boolean DAC960_ExecuteUserCommand(DAC960_Controller_T *Controller, "Unexpected Status %04X\n", Controller, LogicalDriveNumber, Controller->ControllerNumber, - LogicalDriveNumber, Command->CommandStatus); + LogicalDriveNumber, Command->V1.CommandStatus); break; } } @@ -3486,14 +6013,14 @@ static boolean DAC960_ExecuteUserCommand(DAC960_Controller_T *Controller, strcmp(UserCommand, "cancel-consistency-check") == 0) { unsigned char OldRebuildRateConstant; - CommandMailbox->Type3R.CommandOpcode = DAC960_RebuildControl; + CommandMailbox->Type3R.CommandOpcode = DAC960_V1_RebuildControl; CommandMailbox->Type3R.RebuildRateConstant = 0xFF; CommandMailbox->Type3R.BusAddress = Virtual_to_Bus(&OldRebuildRateConstant); DAC960_ExecuteCommand(Command); - switch (Command->CommandStatus) + switch (Command->V1.CommandStatus) { - case DAC960_NormalCompletion: + case DAC960_V1_NormalCompletion: DAC960_UserCritical("Rebuild or Consistency Check Cancelled\n", Controller); break; @@ -3501,7 +6028,7 @@ static boolean DAC960_ExecuteUserCommand(DAC960_Controller_T *Controller, DAC960_UserCritical("Cancellation of Rebuild or " "Consistency Check Failed - " "Unexpected Status %04X\n", - Controller, Command->CommandStatus); + Controller, Command->V1.CommandStatus); break; } } @@ -3515,25 +6042,235 @@ static boolean DAC960_ExecuteUserCommand(DAC960_Controller_T *Controller, /* + DAC960_V2_TranslatePhysicalDevice translates a Physical Device Channel and + TargetID into a Logical Device. It returns true on success and false + on failure. +*/ + +static boolean DAC960_V2_TranslatePhysicalDevice(DAC960_Command_T *Command, + unsigned char Channel, + unsigned char TargetID, + unsigned short + *LogicalDeviceNumber) +{ + DAC960_V2_CommandMailbox_T SavedCommandMailbox, *CommandMailbox; + DAC960_V2_PhysicalToLogicalDevice_T PhysicalToLogicalDevice; + CommandMailbox = &Command->V2.CommandMailbox; + memcpy(&SavedCommandMailbox, CommandMailbox, + sizeof(DAC960_V2_CommandMailbox_T)); + CommandMailbox->PhysicalDeviceInfo.CommandOpcode = DAC960_V2_IOCTL; + CommandMailbox->PhysicalDeviceInfo.CommandControlBits + .DataTransferControllerToHost = true; + CommandMailbox->PhysicalDeviceInfo.CommandControlBits + .NoAutoRequestSense = true; + CommandMailbox->PhysicalDeviceInfo.DataTransferSize = + sizeof(DAC960_V2_PhysicalToLogicalDevice_T); + CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.TargetID = TargetID; + CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.Channel = Channel; + CommandMailbox->PhysicalDeviceInfo.IOCTL_Opcode = + DAC960_V2_TranslatePhysicalToLogicalDevice; + CommandMailbox->Common.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Virtual_to_Bus(&PhysicalToLogicalDevice); + CommandMailbox->Common.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->Common.DataTransferSize; + DAC960_ExecuteCommand(Command); + memcpy(CommandMailbox, &SavedCommandMailbox, + sizeof(DAC960_V2_CommandMailbox_T)); + *LogicalDeviceNumber = PhysicalToLogicalDevice.LogicalDeviceNumber; + return (Command->V2.CommandStatus == DAC960_V2_NormalCompletion); +} + + +/* + DAC960_V2_ExecuteUserCommand executes a User Command for DAC960 V2 Firmware + Controllers. +*/ + +static boolean DAC960_V2_ExecuteUserCommand(DAC960_Controller_T *Controller, + unsigned char *UserCommand) +{ + DAC960_Command_T *Command; + DAC960_V2_CommandMailbox_T *CommandMailbox; + ProcessorFlags_T ProcessorFlags; + unsigned char Channel, TargetID, LogicalDriveNumber; + unsigned short LogicalDeviceNumber; + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + while ((Command = DAC960_AllocateCommand(Controller)) == NULL) + DAC960_WaitForCommand(Controller); + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + Controller->UserStatusLength = 0; + DAC960_V2_ClearCommand(Command); + Command->CommandType = DAC960_ImmediateCommand; + CommandMailbox = &Command->V2.CommandMailbox; + CommandMailbox->Common.CommandOpcode = DAC960_V2_IOCTL; + CommandMailbox->Common.CommandControlBits.DataTransferControllerToHost = true; + CommandMailbox->Common.CommandControlBits.NoAutoRequestSense = true; + if (strcmp(UserCommand, "flush-cache") == 0) + { + CommandMailbox->DeviceOperation.IOCTL_Opcode = DAC960_V2_PauseDevice; + CommandMailbox->DeviceOperation.OperationDevice = + DAC960_V2_RAID_Controller; + DAC960_ExecuteCommand(Command); + DAC960_UserCritical("Cache Flush Completed\n", Controller); + } + else if (strncmp(UserCommand, "kill", 4) == 0 && + DAC960_ParsePhysicalDevice(Controller, &UserCommand[4], + &Channel, &TargetID) && + DAC960_V2_TranslatePhysicalDevice(Command, Channel, TargetID, + &LogicalDeviceNumber)) + { + CommandMailbox->SetDeviceState.LogicalDevice.LogicalDeviceNumber = + LogicalDeviceNumber; + CommandMailbox->SetDeviceState.IOCTL_Opcode = + DAC960_V2_SetDeviceState; + CommandMailbox->SetDeviceState.DeviceState.PhysicalDeviceState = + DAC960_V2_Device_Dead; + DAC960_ExecuteCommand(Command); + DAC960_UserCritical("Kill of Physical Device %d:%d %s\n", + Controller, Channel, TargetID, + (Command->V2.CommandStatus + == DAC960_V2_NormalCompletion + ? "Succeeded" : "Failed")); + } + else if (strncmp(UserCommand, "make-online", 11) == 0 && + DAC960_ParsePhysicalDevice(Controller, &UserCommand[11], + &Channel, &TargetID) && + DAC960_V2_TranslatePhysicalDevice(Command, Channel, TargetID, + &LogicalDeviceNumber)) + { + CommandMailbox->SetDeviceState.LogicalDevice.LogicalDeviceNumber = + LogicalDeviceNumber; + CommandMailbox->SetDeviceState.IOCTL_Opcode = + DAC960_V2_SetDeviceState; + CommandMailbox->SetDeviceState.DeviceState.PhysicalDeviceState = + DAC960_V2_Device_Online; + DAC960_ExecuteCommand(Command); + DAC960_UserCritical("Make Online of Physical Device %d:%d %s\n", + Controller, Channel, TargetID, + (Command->V2.CommandStatus + == DAC960_V2_NormalCompletion + ? "Succeeded" : "Failed")); + } + else if (strncmp(UserCommand, "make-standby", 12) == 0 && + DAC960_ParsePhysicalDevice(Controller, &UserCommand[12], + &Channel, &TargetID) && + DAC960_V2_TranslatePhysicalDevice(Command, Channel, TargetID, + &LogicalDeviceNumber)) + { + CommandMailbox->SetDeviceState.LogicalDevice.LogicalDeviceNumber = + LogicalDeviceNumber; + CommandMailbox->SetDeviceState.IOCTL_Opcode = + DAC960_V2_SetDeviceState; + CommandMailbox->SetDeviceState.DeviceState.PhysicalDeviceState = + DAC960_V2_Device_Standby; + DAC960_ExecuteCommand(Command); + DAC960_UserCritical("Make Standby of Physical Device %d:%d %s\n", + Controller, Channel, TargetID, + (Command->V2.CommandStatus + == DAC960_V2_NormalCompletion + ? "Succeeded" : "Failed")); + } + else if (strncmp(UserCommand, "rebuild", 7) == 0 && + DAC960_ParsePhysicalDevice(Controller, &UserCommand[7], + &Channel, &TargetID) && + DAC960_V2_TranslatePhysicalDevice(Command, Channel, TargetID, + &LogicalDeviceNumber)) + { + CommandMailbox->LogicalDeviceInfo.LogicalDevice.LogicalDeviceNumber = + LogicalDeviceNumber; + CommandMailbox->LogicalDeviceInfo.IOCTL_Opcode = + DAC960_V2_RebuildDeviceStart; + DAC960_ExecuteCommand(Command); + DAC960_UserCritical("Rebuild of Physical Device %d:%d %s\n", + Controller, Channel, TargetID, + (Command->V2.CommandStatus + == DAC960_V2_NormalCompletion + ? "Initiated" : "Not Initiated")); + } + else if (strncmp(UserCommand, "cancel-rebuild", 14) == 0 && + DAC960_ParsePhysicalDevice(Controller, &UserCommand[14], + &Channel, &TargetID) && + DAC960_V2_TranslatePhysicalDevice(Command, Channel, TargetID, + &LogicalDeviceNumber)) + { + CommandMailbox->LogicalDeviceInfo.LogicalDevice.LogicalDeviceNumber = + LogicalDeviceNumber; + CommandMailbox->LogicalDeviceInfo.IOCTL_Opcode = + DAC960_V2_RebuildDeviceStop; + DAC960_ExecuteCommand(Command); + DAC960_UserCritical("Rebuild of Physical Device %d:%d %s\n", + Controller, Channel, TargetID, + (Command->V2.CommandStatus + == DAC960_V2_NormalCompletion + ? "Cancelled" : "Not Cancelled")); + } + else if (strncmp(UserCommand, "check-consistency", 17) == 0 && + DAC960_ParseLogicalDrive(Controller, &UserCommand[17], + &LogicalDriveNumber)) + { + CommandMailbox->ConsistencyCheck.LogicalDevice.LogicalDeviceNumber = + LogicalDriveNumber; + CommandMailbox->ConsistencyCheck.IOCTL_Opcode = + DAC960_V2_ConsistencyCheckStart; + CommandMailbox->ConsistencyCheck.RestoreConsistency = true; + CommandMailbox->ConsistencyCheck.InitializedAreaOnly = false; + DAC960_ExecuteCommand(Command); + DAC960_UserCritical("Consistency Check of Logical Drive %d " + "(/dev/rd/c%dd%d) %s\n", + Controller, LogicalDriveNumber, + Controller->ControllerNumber, + LogicalDriveNumber, + (Command->V2.CommandStatus + == DAC960_V2_NormalCompletion + ? "Initiated" : "Not Initiated")); + } + else if (strncmp(UserCommand, "cancel-consistency-check", 24) == 0 && + DAC960_ParseLogicalDrive(Controller, &UserCommand[24], + &LogicalDriveNumber)) + { + CommandMailbox->ConsistencyCheck.LogicalDevice.LogicalDeviceNumber = + LogicalDriveNumber; + CommandMailbox->ConsistencyCheck.IOCTL_Opcode = + DAC960_V2_ConsistencyCheckStop; + DAC960_ExecuteCommand(Command); + DAC960_UserCritical("Consistency Check of Logical Drive %d " + "(/dev/rd/c%dd%d) %s\n", + Controller, LogicalDriveNumber, + Controller->ControllerNumber, + LogicalDriveNumber, + (Command->V2.CommandStatus + == DAC960_V2_NormalCompletion + ? "Cancelled" : "Not Cancelled")); + } + else DAC960_UserCritical("Illegal User Command: '%s'\n", + Controller, UserCommand); + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + DAC960_DeallocateCommand(Command); + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + return true; +} + + +/* DAC960_ProcReadStatus implements reading /proc/rd/status. */ static int DAC960_ProcReadStatus(char *Page, char **Start, off_t Offset, int Count, int *EOF, void *Data) { - char *StatusMessage = "OK\n"; + unsigned char *StatusMessage = "OK\n"; int ControllerNumber, BytesAvailable; for (ControllerNumber = 0; ControllerNumber < DAC960_ControllerCount; ControllerNumber++) { DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber]; - DAC960_Enquiry_T *Enquiry; if (Controller == NULL) continue; - Enquiry = &Controller->Enquiry[Controller->EnquiryIndex]; - if (Enquiry->CriticalLogicalDriveCount > 0 || - Enquiry->OfflineLogicalDriveCount > 0 || - Enquiry->DeadDriveCount > 0) + if (Controller->MonitoringAlertMode) { StatusMessage = "ALERT\n"; break; @@ -3568,7 +6305,7 @@ static int DAC960_ProcReadInitialStatus(char *Page, char **Start, off_t Offset, } if (Count <= 0) return 0; *Start = Page; - memcpy(Page, &Controller->InitialStatusBuffer[Offset], Count); + memcpy(Page, &Controller->CombinedStatusBuffer[Offset], Count); return Count; } @@ -3581,6 +6318,9 @@ static int DAC960_ProcReadCurrentStatus(char *Page, char **Start, off_t Offset, int Count, int *EOF, void *Data) { DAC960_Controller_T *Controller = (DAC960_Controller_T *) Data; + unsigned char *StatusMessage = + "No Rebuild or Consistency Check in Progress\n"; + int ProgressMessageLength = strlen(StatusMessage); int BytesAvailable; if (jiffies != Controller->LastCurrentStatusTime) { @@ -3588,22 +6328,20 @@ static int DAC960_ProcReadCurrentStatus(char *Page, char **Start, off_t Offset, DAC960_AnnounceDriver(Controller); DAC960_ReportControllerConfiguration(Controller); DAC960_ReportDeviceConfiguration(Controller); - Controller->CurrentStatusBuffer[Controller->CurrentStatusLength++] = ' '; - Controller->CurrentStatusBuffer[Controller->CurrentStatusLength++] = ' '; - if (Controller->RebuildProgressLength > 0) - { - strcpy(&Controller->CurrentStatusBuffer - [Controller->CurrentStatusLength], - Controller->RebuildProgressBuffer); - Controller->CurrentStatusLength += Controller->RebuildProgressLength; - } - else + if (Controller->ProgressBufferLength > 0) + ProgressMessageLength = Controller->ProgressBufferLength; + if (DAC960_CheckStatusBuffer(Controller, 2 + ProgressMessageLength)) { - char *StatusMessage = "No Rebuild or Consistency Check in Progress\n"; - strcpy(&Controller->CurrentStatusBuffer - [Controller->CurrentStatusLength], - StatusMessage); - Controller->CurrentStatusLength += strlen(StatusMessage); + unsigned char *CurrentStatusBuffer = Controller->CurrentStatusBuffer; + CurrentStatusBuffer[Controller->CurrentStatusLength++] = ' '; + CurrentStatusBuffer[Controller->CurrentStatusLength++] = ' '; + if (Controller->ProgressBufferLength > 0) + strcpy(&CurrentStatusBuffer[Controller->CurrentStatusLength], + Controller->ProgressBuffer); + else + strcpy(&CurrentStatusBuffer[Controller->CurrentStatusLength], + StatusMessage); + Controller->CurrentStatusLength += ProgressMessageLength; } Controller->LastCurrentStatusTime = jiffies; } @@ -3649,7 +6387,7 @@ static int DAC960_ProcWriteUserCommand(File_T *File, const char *Buffer, unsigned long Count, void *Data) { DAC960_Controller_T *Controller = (DAC960_Controller_T *) Data; - char CommandBuffer[80]; + unsigned char CommandBuffer[80]; int Length; if (Count > sizeof(CommandBuffer)-1) return -EINVAL; copy_from_user(CommandBuffer, Buffer, Count); @@ -3657,21 +6395,25 @@ static int DAC960_ProcWriteUserCommand(File_T *File, const char *Buffer, Length = strlen(CommandBuffer); if (CommandBuffer[Length-1] == '\n') CommandBuffer[--Length] = '\0'; - return (DAC960_ExecuteUserCommand(Controller, CommandBuffer) - ? Count : -EBUSY); + if (Controller->FirmwareType == DAC960_V1_Controller) + return (DAC960_V1_ExecuteUserCommand(Controller, CommandBuffer) + ? Count : -EBUSY); + else + return (DAC960_V2_ExecuteUserCommand(Controller, CommandBuffer) + ? Count : -EBUSY); } /* - DAC960_CreateProcEntries creates the /proc/driver/rd/... entries - for the DAC960 Driver. + DAC960_CreateProcEntries creates the /proc/rd/... entries for the + DAC960 Driver. */ static void DAC960_CreateProcEntries(void) { - static PROC_DirectoryEntry_T *StatusProcEntry; + PROC_DirectoryEntry_T *StatusProcEntry; int ControllerNumber; - DAC960_ProcDirectoryEntry = proc_mkdir("driver/rd", NULL); + DAC960_ProcDirectoryEntry = proc_mkdir("rd", NULL); StatusProcEntry = create_proc_read_entry("status", 0, DAC960_ProcDirectoryEntry, DAC960_ProcReadStatus, NULL); @@ -3684,29 +6426,42 @@ static void DAC960_CreateProcEntries(void) PROC_DirectoryEntry_T *UserCommandProcEntry; if (Controller == NULL) continue; ControllerProcEntry = proc_mkdir(Controller->ControllerName, - DAC960_ProcDirectoryEntry); - create_proc_read_entry("initial_status",0,ControllerProcEntry, + DAC960_ProcDirectoryEntry); + create_proc_read_entry("initial_status", 0, ControllerProcEntry, DAC960_ProcReadInitialStatus, Controller); - create_proc_read_entry("current_status",0,ControllerProcEntry, + create_proc_read_entry("current_status", 0, ControllerProcEntry, DAC960_ProcReadCurrentStatus, Controller); UserCommandProcEntry = - create_proc_read_entry("user_command", S_IWUSR|S_IRUSR, - ControllerProcEntry, - DAC960_ProcReadUserCommand, Controller); + create_proc_read_entry("user_command", S_IWUSR | S_IRUSR, + ControllerProcEntry, DAC960_ProcReadUserCommand, + Controller); UserCommandProcEntry->write_proc = DAC960_ProcWriteUserCommand; + Controller->ControllerProcEntry = ControllerProcEntry; } } /* - DAC960_DestroyProcEntries destroys the /proc/rd/... entries for the DAC960 - Driver. + DAC960_DestroyProcEntries destroys the /proc/rd/... entries for the + DAC960 Driver. */ static void DAC960_DestroyProcEntries(void) { - /* FIXME */ - remove_proc_entry("driver/rd", NULL); + int ControllerNumber; + for (ControllerNumber = 0; + ControllerNumber < DAC960_ControllerCount; + ControllerNumber++) + { + DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber]; + if (Controller == NULL) continue; + remove_proc_entry("initial_status", Controller->ControllerProcEntry); + remove_proc_entry("current_status", Controller->ControllerProcEntry); + remove_proc_entry("user_command", Controller->ControllerProcEntry); + remove_proc_entry(Controller->ControllerName, DAC960_ProcDirectoryEntry); + } + remove_proc_entry("rd/status", NULL); + remove_proc_entry("rd", NULL); } @@ -3719,18 +6474,8 @@ static void DAC960_DestroyProcEntries(void) int init_module(void) { - int ControllerNumber; DAC960_Initialize(); - if (DAC960_ActiveControllerCount == 0) return -1; - for (ControllerNumber = 0; - ControllerNumber < DAC960_ControllerCount; - ControllerNumber++) - { - DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber]; - if (Controller == NULL) continue; - DAC960_InitializeGenericDiskInfo(&Controller->GenericDiskInfo); - } - return 0; + return (DAC960_ActiveControllerCount > 0 ? 0 : -1); } diff --git a/drivers/block/DAC960.h b/drivers/block/DAC960.h index 237a8deef..a7062899e 100644 --- a/drivers/block/DAC960.h +++ b/drivers/block/DAC960.h @@ -1,8 +1,8 @@ /* - Linux Driver for Mylex DAC960 and DAC1100 PCI RAID Controllers + Linux Driver for Mylex DAC960/AcceleRAID/eXtremeRAID PCI RAID Controllers - Copyright 1998-1999 by Leonard N. Zubkoff <lnz@dandelion.com> + Copyright 1998-2000 by Leonard N. Zubkoff <lnz@dandelion.com> This program is free software; you may redistribute and/or modify it under the terms of the GNU General Public License Version 2 as published by the @@ -27,27 +27,41 @@ /* - Define the maximum number of Controller Channels supported by this driver. + Define the maximum number of Controller Channels supported by DAC960 + V1 and V2 Firmware Controllers. */ -#define DAC960_MaxChannels 3 +#define DAC960_V1_MaxChannels 3 +#define DAC960_V2_MaxChannels 4 /* - Define the maximum number of Targets per Channel supported by this driver. + Define the maximum number of Targets per Channel supported by DAC960 + V1 and V2 Firmware Controllers. */ -#define DAC960_MaxTargets 16 +#define DAC960_V1_MaxTargets 16 +#define DAC960_V2_MaxTargets 128 /* - Define the maximum number of Logical Drives supported by any DAC960 model. + Define the maximum number of Logical Drives supported by DAC960 + V1 and V2 Firmware Controllers. */ #define DAC960_MaxLogicalDrives 32 /* + Define the maximum number of Physical Devices supported by DAC960 + V1 and V2 Firmware Controllers. +*/ + +#define DAC960_V1_MaxPhysicalDevices 45 +#define DAC960_V2_MaxPhysicalDevices 272 + + +/* Define a Boolean data type. */ @@ -72,149 +86,264 @@ typedef unsigned long DAC960_PCI_Address_T; Define a 32 bit Bus Address data type. */ -typedef unsigned int DAC960_BusAddress_T; +typedef unsigned int DAC960_BusAddress32_T; + + +/* + Define a 64 bit Bus Address data type. +*/ + +typedef unsigned long long DAC960_BusAddress64_T; /* Define a 32 bit Byte Count data type. */ -typedef unsigned int DAC960_ByteCount_T; +typedef unsigned int DAC960_ByteCount32_T; + + +/* + Define a 64 bit Byte Count data type. +*/ + +typedef unsigned long long DAC960_ByteCount64_T; + + +/* + Define the SCSI INQUIRY Standard Data structure. +*/ + +typedef struct DAC960_SCSI_Inquiry +{ + unsigned char PeripheralDeviceType:5; /* Byte 0 Bits 0-4 */ + unsigned char PeripheralQualifier:3; /* Byte 0 Bits 5-7 */ + unsigned char DeviceTypeModifier:7; /* Byte 1 Bits 0-6 */ + boolean RMB:1; /* Byte 1 Bit 7 */ + unsigned char ANSI_ApprovedVersion:3; /* Byte 2 Bits 0-2 */ + unsigned char ECMA_Version:3; /* Byte 2 Bits 3-5 */ + unsigned char ISO_Version:2; /* Byte 2 Bits 6-7 */ + unsigned char ResponseDataFormat:4; /* Byte 3 Bits 0-3 */ + unsigned char :2; /* Byte 3 Bits 4-5 */ + boolean TrmIOP:1; /* Byte 3 Bit 6 */ + boolean AENC:1; /* Byte 3 Bit 7 */ + unsigned char AdditionalLength; /* Byte 4 */ + unsigned char :8; /* Byte 5 */ + unsigned char :8; /* Byte 6 */ + boolean SftRe:1; /* Byte 7 Bit 0 */ + boolean CmdQue:1; /* Byte 7 Bit 1 */ + boolean :1; /* Byte 7 Bit 2 */ + boolean Linked:1; /* Byte 7 Bit 3 */ + boolean Sync:1; /* Byte 7 Bit 4 */ + boolean WBus16:1; /* Byte 7 Bit 5 */ + boolean WBus32:1; /* Byte 7 Bit 6 */ + boolean RelAdr:1; /* Byte 7 Bit 7 */ + unsigned char VendorIdentification[8]; /* Bytes 8-15 */ + unsigned char ProductIdentification[16]; /* Bytes 16-31 */ + unsigned char ProductRevisionLevel[4]; /* Bytes 32-35 */ +} +DAC960_SCSI_Inquiry_T; /* - Define the DAC960 Command Opcodes. + Define the SCSI INQUIRY Unit Serial Number structure. +*/ + +typedef struct DAC960_SCSI_Inquiry_UnitSerialNumber +{ + unsigned char PeripheralDeviceType:5; /* Byte 0 Bits 0-4 */ + unsigned char PeripheralQualifier:3; /* Byte 0 Bits 5-7 */ + unsigned char PageCode; /* Byte 1 */ + unsigned char :8; /* Byte 2 */ + unsigned char PageLength; /* Byte 3 */ + unsigned char ProductSerialNumber[28]; /* Bytes 4-31 */ +} +DAC960_SCSI_Inquiry_UnitSerialNumber_T; + + +/* + Define the SCSI REQUEST SENSE Sense Key type. +*/ + +typedef enum +{ + DAC960_SenseKey_NoSense = 0x0, + DAC960_SenseKey_RecoveredError = 0x1, + DAC960_SenseKey_NotReady = 0x2, + DAC960_SenseKey_MediumError = 0x3, + DAC960_SenseKey_HardwareError = 0x4, + DAC960_SenseKey_IllegalRequest = 0x5, + DAC960_SenseKey_UnitAttention = 0x6, + DAC960_SenseKey_DataProtect = 0x7, + DAC960_SenseKey_BlankCheck = 0x8, + DAC960_SenseKey_VendorSpecific = 0x9, + DAC960_SenseKey_CopyAborted = 0xA, + DAC960_SenseKey_AbortedCommand = 0xB, + DAC960_SenseKey_Equal = 0xC, + DAC960_SenseKey_VolumeOverflow = 0xD, + DAC960_SenseKey_Miscompare = 0xE, + DAC960_SenseKey_Reserved = 0xF +} +__attribute__ ((packed)) +DAC960_SCSI_RequestSenseKey_T; + + +/* + Define the SCSI REQUEST SENSE structure. +*/ + +typedef struct DAC960_SCSI_RequestSense +{ + unsigned char ErrorCode:7; /* Byte 0 Bits 0-6 */ + boolean Valid:1; /* Byte 0 Bit 7 */ + unsigned char SegmentNumber; /* Byte 1 */ + DAC960_SCSI_RequestSenseKey_T SenseKey:4; /* Byte 2 Bits 0-3 */ + unsigned char :1; /* Byte 2 Bit 4 */ + boolean ILI:1; /* Byte 2 Bit 5 */ + boolean EOM:1; /* Byte 2 Bit 6 */ + boolean Filemark:1; /* Byte 2 Bit 7 */ + unsigned char Information[4]; /* Bytes 3-6 */ + unsigned char AdditionalSenseLength; /* Byte 7 */ + unsigned char CommandSpecificInformation[4]; /* Bytes 8-11 */ + unsigned char AdditionalSenseCode; /* Byte 12 */ + unsigned char AdditionalSenseCodeQualifier; /* Byte 13 */ +} +DAC960_SCSI_RequestSense_T; + + +/* + Define the DAC960 V1 Firmware Command Opcodes. */ typedef enum { /* I/O Commands */ - DAC960_ReadExtended = 0x33, - DAC960_WriteExtended = 0x34, - DAC960_ReadAheadExtended = 0x35, - DAC960_ReadExtendedWithScatterGather = 0xB3, - DAC960_WriteExtendedWithScatterGather = 0xB4, - DAC960_Read = 0x36, - DAC960_ReadWithOldScatterGather = 0xB6, - DAC960_Write = 0x37, - DAC960_WriteWithOldScatterGather = 0xB7, - DAC960_DCDB = 0x04, - DAC960_DCDBWithScatterGather = 0x84, - DAC960_Flush = 0x0A, + DAC960_V1_ReadExtended = 0x33, + DAC960_V1_WriteExtended = 0x34, + DAC960_V1_ReadAheadExtended = 0x35, + DAC960_V1_ReadExtendedWithScatterGather = 0xB3, + DAC960_V1_WriteExtendedWithScatterGather = 0xB4, + DAC960_V1_Read = 0x36, + DAC960_V1_ReadWithOldScatterGather = 0xB6, + DAC960_V1_Write = 0x37, + DAC960_V1_WriteWithOldScatterGather = 0xB7, + DAC960_V1_DCDB = 0x04, + DAC960_V1_DCDBWithScatterGather = 0x84, + DAC960_V1_Flush = 0x0A, /* Controller Status Related Commands */ - DAC960_Enquiry = 0x53, - DAC960_Enquiry2 = 0x1C, - DAC960_GetLogicalDriveElement = 0x55, - DAC960_GetLogicalDriveInformation = 0x19, - DAC960_IOPortRead = 0x39, - DAC960_IOPortWrite = 0x3A, - DAC960_GetSDStats = 0x3E, - DAC960_GetPDStats = 0x3F, - DAC960_PerformEventLogOperation = 0x72, + DAC960_V1_Enquiry = 0x53, + DAC960_V1_Enquiry2 = 0x1C, + DAC960_V1_GetLogicalDriveElement = 0x55, + DAC960_V1_GetLogicalDriveInformation = 0x19, + DAC960_V1_IOPortRead = 0x39, + DAC960_V1_IOPortWrite = 0x3A, + DAC960_V1_GetSDStats = 0x3E, + DAC960_V1_GetPDStats = 0x3F, + DAC960_V1_PerformEventLogOperation = 0x72, /* Device Related Commands */ - DAC960_StartDevice = 0x10, - DAC960_GetDeviceState = 0x50, - DAC960_StopChannel = 0x13, - DAC960_StartChannel = 0x12, - DAC960_ResetChannel = 0x1A, + DAC960_V1_StartDevice = 0x10, + DAC960_V1_GetDeviceState = 0x50, + DAC960_V1_StopChannel = 0x13, + DAC960_V1_StartChannel = 0x12, + DAC960_V1_ResetChannel = 0x1A, /* Commands Associated with Data Consistency and Errors */ - DAC960_Rebuild = 0x09, - DAC960_RebuildAsync = 0x16, - DAC960_CheckConsistency = 0x0F, - DAC960_CheckConsistencyAsync = 0x1E, - DAC960_RebuildStat = 0x0C, - DAC960_GetRebuildProgress = 0x27, - DAC960_RebuildControl = 0x1F, - DAC960_ReadBadBlockTable = 0x0B, - DAC960_ReadBadDataTable = 0x25, - DAC960_ClearBadDataTable = 0x26, - DAC960_GetErrorTable = 0x17, - DAC960_AddCapacityAsync = 0x2A, + DAC960_V1_Rebuild = 0x09, + DAC960_V1_RebuildAsync = 0x16, + DAC960_V1_CheckConsistency = 0x0F, + DAC960_V1_CheckConsistencyAsync = 0x1E, + DAC960_V1_RebuildStat = 0x0C, + DAC960_V1_GetRebuildProgress = 0x27, + DAC960_V1_RebuildControl = 0x1F, + DAC960_V1_ReadBadBlockTable = 0x0B, + DAC960_V1_ReadBadDataTable = 0x25, + DAC960_V1_ClearBadDataTable = 0x26, + DAC960_V1_GetErrorTable = 0x17, + DAC960_V1_AddCapacityAsync = 0x2A, /* Configuration Related Commands */ - DAC960_ReadConfig2 = 0x3D, - DAC960_WriteConfig2 = 0x3C, - DAC960_ReadConfigurationOnDisk = 0x4A, - DAC960_WriteConfigurationOnDisk = 0x4B, - DAC960_ReadConfiguration = 0x4E, - DAC960_ReadBackupConfiguration = 0x4D, - DAC960_WriteConfiguration = 0x4F, - DAC960_AddConfiguration = 0x4C, - DAC960_ReadConfigurationLabel = 0x48, - DAC960_WriteConfigurationLabel = 0x49, + DAC960_V1_ReadConfig2 = 0x3D, + DAC960_V1_WriteConfig2 = 0x3C, + DAC960_V1_ReadConfigurationOnDisk = 0x4A, + DAC960_V1_WriteConfigurationOnDisk = 0x4B, + DAC960_V1_ReadConfiguration = 0x4E, + DAC960_V1_ReadBackupConfiguration = 0x4D, + DAC960_V1_WriteConfiguration = 0x4F, + DAC960_V1_AddConfiguration = 0x4C, + DAC960_V1_ReadConfigurationLabel = 0x48, + DAC960_V1_WriteConfigurationLabel = 0x49, /* Firmware Upgrade Related Commands */ - DAC960_LoadImage = 0x20, - DAC960_StoreImage = 0x21, - DAC960_ProgramImage = 0x22, + DAC960_V1_LoadImage = 0x20, + DAC960_V1_StoreImage = 0x21, + DAC960_V1_ProgramImage = 0x22, /* Diagnostic Commands */ - DAC960_SetDiagnosticMode = 0x31, - DAC960_RunDiagnostic = 0x32, + DAC960_V1_SetDiagnosticMode = 0x31, + DAC960_V1_RunDiagnostic = 0x32, /* Subsystem Service Commands */ - DAC960_GetSubsystemData = 0x70, - DAC960_SetSubsystemParameters = 0x71 + DAC960_V1_GetSubsystemData = 0x70, + DAC960_V1_SetSubsystemParameters = 0x71 } __attribute__ ((packed)) -DAC960_CommandOpcode_T; +DAC960_V1_CommandOpcode_T; /* - Define the DAC960 Command Identifier type. + Define the DAC960 V1 Firmware Command Identifier type. */ -typedef unsigned char DAC960_CommandIdentifier_T; +typedef unsigned char DAC960_V1_CommandIdentifier_T; /* - Define the DAC960 Command Status Codes. + Define the DAC960 V1 Firmware Command Status Codes. */ -#define DAC960_NormalCompletion 0x0000 /* Common */ -#define DAC960_CheckConditionReceived 0x0002 /* Common */ -#define DAC960_NoDeviceAtAddress 0x0102 /* Common */ -#define DAC960_InvalidDeviceAddress 0x0105 /* Common */ -#define DAC960_InvalidParameter 0x0105 /* Common */ -#define DAC960_IrrecoverableDataError 0x0001 /* I/O */ -#define DAC960_LogicalDriveNonexistentOrOffline 0x0002 /* I/O */ -#define DAC960_AccessBeyondEndOfLogicalDrive 0x0105 /* I/O */ -#define DAC960_BadDataEncountered 0x010C /* I/O */ -#define DAC960_DeviceBusy 0x0008 /* DCDB */ -#define DAC960_DeviceNonresponsive 0x000E /* DCDB */ -#define DAC960_CommandTerminatedAbnormally 0x000F /* DCDB */ -#define DAC960_UnableToStartDevice 0x0002 /* Device */ -#define DAC960_InvalidChannelOrTargetOrModifier 0x0105 /* Device */ -#define DAC960_ChannelBusy 0x0106 /* Device */ -#define DAC960_ChannelNotStopped 0x0002 /* Device */ -#define DAC960_AttemptToRebuildOnlineDrive 0x0002 /* Consistency */ -#define DAC960_RebuildBadBlocksEncountered 0x0003 /* Consistency */ -#define DAC960_NewDiskFailedDuringRebuild 0x0004 /* Consistency */ -#define DAC960_RebuildOrCheckAlreadyInProgress 0x0106 /* Consistency */ -#define DAC960_DependentDiskIsDead 0x0002 /* Consistency */ -#define DAC960_InconsistentBlocksFound 0x0003 /* Consistency */ -#define DAC960_InvalidOrNonredundantLogicalDrive 0x0105 /* Consistency */ -#define DAC960_NoRebuildOrCheckInProgress 0x0105 /* Consistency */ -#define DAC960_RebuildInProgress_DataValid 0x0000 /* Consistency */ -#define DAC960_RebuildFailed_LogicalDriveFailure 0x0002 /* Consistency */ -#define DAC960_RebuildFailed_BadBlocksOnOther 0x0003 /* Consistency */ -#define DAC960_RebuildFailed_NewDriveFailed 0x0004 /* Consistency */ -#define DAC960_RebuildSuccessful 0x0100 /* Consistency */ -#define DAC960_RebuildSuccessfullyTerminated 0x0107 /* Consistency */ -#define DAC960_AddCapacityInProgress 0x0004 /* Consistency */ -#define DAC960_AddCapacityFailedOrSuspended 0x00F4 /* Consistency */ -#define DAC960_Config2ChecksumError 0x0002 /* Configuration */ -#define DAC960_ConfigurationSuspended 0x0106 /* Configuration */ -#define DAC960_FailedToConfigureNVRAM 0x0105 /* Configuration */ -#define DAC960_ConfigurationNotSavedStateChange 0x0106 /* Configuration */ -#define DAC960_SubsystemNotInstalled 0x0001 /* Subsystem */ -#define DAC960_SubsystemFailed 0x0002 /* Subsystem */ -#define DAC960_SubsystemBusy 0x0106 /* Subsystem */ - -typedef unsigned short DAC960_CommandStatus_T; +#define DAC960_V1_NormalCompletion 0x0000 /* Common */ +#define DAC960_V1_CheckConditionReceived 0x0002 /* Common */ +#define DAC960_V1_NoDeviceAtAddress 0x0102 /* Common */ +#define DAC960_V1_InvalidDeviceAddress 0x0105 /* Common */ +#define DAC960_V1_InvalidParameter 0x0105 /* Common */ +#define DAC960_V1_IrrecoverableDataError 0x0001 /* I/O */ +#define DAC960_V1_LogicalDriveNonexistentOrOffline 0x0002 /* I/O */ +#define DAC960_V1_AccessBeyondEndOfLogicalDrive 0x0105 /* I/O */ +#define DAC960_V1_BadDataEncountered 0x010C /* I/O */ +#define DAC960_V1_DeviceBusy 0x0008 /* DCDB */ +#define DAC960_V1_DeviceNonresponsive 0x000E /* DCDB */ +#define DAC960_V1_CommandTerminatedAbnormally 0x000F /* DCDB */ +#define DAC960_V1_UnableToStartDevice 0x0002 /* Device */ +#define DAC960_V1_InvalidChannelOrTargetOrModifier 0x0105 /* Device */ +#define DAC960_V1_ChannelBusy 0x0106 /* Device */ +#define DAC960_V1_ChannelNotStopped 0x0002 /* Device */ +#define DAC960_V1_AttemptToRebuildOnlineDrive 0x0002 /* Consistency */ +#define DAC960_V1_RebuildBadBlocksEncountered 0x0003 /* Consistency */ +#define DAC960_V1_NewDiskFailedDuringRebuild 0x0004 /* Consistency */ +#define DAC960_V1_RebuildOrCheckAlreadyInProgress 0x0106 /* Consistency */ +#define DAC960_V1_DependentDiskIsDead 0x0002 /* Consistency */ +#define DAC960_V1_InconsistentBlocksFound 0x0003 /* Consistency */ +#define DAC960_V1_InvalidOrNonredundantLogicalDrive 0x0105 /* Consistency */ +#define DAC960_V1_NoRebuildOrCheckInProgress 0x0105 /* Consistency */ +#define DAC960_V1_RebuildInProgress_DataValid 0x0000 /* Consistency */ +#define DAC960_V1_RebuildFailed_LogicalDriveFailure 0x0002 /* Consistency */ +#define DAC960_V1_RebuildFailed_BadBlocksOnOther 0x0003 /* Consistency */ +#define DAC960_V1_RebuildFailed_NewDriveFailed 0x0004 /* Consistency */ +#define DAC960_V1_RebuildSuccessful 0x0100 /* Consistency */ +#define DAC960_V1_RebuildSuccessfullyTerminated 0x0107 /* Consistency */ +#define DAC960_V1_AddCapacityInProgress 0x0004 /* Consistency */ +#define DAC960_V1_AddCapacityFailedOrSuspended 0x00F4 /* Consistency */ +#define DAC960_V1_Config2ChecksumError 0x0002 /* Configuration */ +#define DAC960_V1_ConfigurationSuspended 0x0106 /* Configuration */ +#define DAC960_V1_FailedToConfigureNVRAM 0x0105 /* Configuration */ +#define DAC960_V1_ConfigurationNotSavedStateChange 0x0106 /* Configuration */ +#define DAC960_V1_SubsystemNotInstalled 0x0001 /* Subsystem */ +#define DAC960_V1_SubsystemFailed 0x0002 /* Subsystem */ +#define DAC960_V1_SubsystemBusy 0x0106 /* Subsystem */ + +typedef unsigned short DAC960_V1_CommandStatus_T; /* - Define the Enquiry reply structure. + Define the DAC960 V1 Firmware Enquiry Command reply structure. */ -typedef struct DAC960_Enquiry +typedef struct DAC960_V1_Enquiry { unsigned char NumberOfLogicalDrives; /* Byte 0 */ unsigned int :24; /* Bytes 1-3 */ @@ -229,15 +358,15 @@ typedef struct DAC960_Enquiry unsigned char MinorFirmwareVersion; /* Byte 136 */ unsigned char MajorFirmwareVersion; /* Byte 137 */ enum { - DAC960_NoStandbyRebuildOrCheckInProgress = 0x00, - DAC960_StandbyRebuildInProgress = 0x01, - DAC960_BackgroundRebuildInProgress = 0x02, - DAC960_BackgroundCheckInProgress = 0x03, - DAC960_StandbyRebuildCompletedWithError = 0xFF, - DAC960_BackgroundRebuildOrCheckFailed_DriveFailed = 0xF0, - DAC960_BackgroundRebuildOrCheckFailed_LogicalDriveFailed = 0xF1, - DAC960_BackgroundRebuildOrCheckFailed_OtherCauses = 0xF2, - DAC960_BackgroundRebuildOrCheckSuccessfullyTerminated = 0xF3 + DAC960_V1_NoStandbyRebuildOrCheckInProgress = 0x00, + DAC960_V1_StandbyRebuildInProgress = 0x01, + DAC960_V1_BackgroundRebuildInProgress = 0x02, + DAC960_V1_BackgroundCheckInProgress = 0x03, + DAC960_V1_StandbyRebuildCompletedWithError = 0xFF, + DAC960_V1_BackgroundRebuildOrCheckFailed_DriveFailed = 0xF0, + DAC960_V1_BackgroundRebuildOrCheckFailed_LogicalDriveFailed = 0xF1, + DAC960_V1_BackgroundRebuildOrCheckFailed_OtherCauses = 0xF2, + DAC960_V1_BackgroundRebuildOrCheckSuccessfullyTerminated = 0xF3 } __attribute__ ((packed)) RebuildFlag; /* Byte 138 */ unsigned char MaxCommands; /* Byte 139 */ unsigned char OfflineLogicalDriveCount; /* Byte 140 */ @@ -261,40 +390,40 @@ typedef struct DAC960_Enquiry unsigned char Reserved[62]; /* Bytes 195-255 */ } __attribute__ ((packed)) -DAC960_Enquiry_T; +DAC960_V1_Enquiry_T; /* - Define the Enquiry2 reply structure. + Define the DAC960 V1 Firmware Enquiry2 Command reply structure. */ -typedef struct DAC960_Enquiry2 +typedef struct DAC960_V1_Enquiry2 { struct { enum { - DAC960_P_PD_PU = 0x01, - DAC960_PL = 0x02, - DAC960_PG = 0x10, - DAC960_PJ = 0x11, - DAC960_PR = 0x12, - DAC960_PT = 0x13, - DAC960_PTL0 = 0x14, - DAC960_PRL = 0x15, - DAC960_PTL1 = 0x16, - DAC1164_P = 0x20 + DAC960_V1_P_PD_PU = 0x01, + DAC960_V1_PL = 0x02, + DAC960_V1_PG = 0x10, + DAC960_V1_PJ = 0x11, + DAC960_V1_PR = 0x12, + DAC960_V1_PT = 0x13, + DAC960_V1_PTL0 = 0x14, + DAC960_V1_PRL = 0x15, + DAC960_V1_PTL1 = 0x16, + DAC960_V1_1164P = 0x20 } __attribute__ ((packed)) SubModel; /* Byte 0 */ unsigned char ActualChannels; /* Byte 1 */ enum { - DAC960_FiveChannelBoard = 0x01, - DAC960_ThreeChannelBoard = 0x02, - DAC960_TwoChannelBoard = 0x03, - DAC960_ThreeChannelASIC_DAC = 0x04 + DAC960_V1_FiveChannelBoard = 0x01, + DAC960_V1_ThreeChannelBoard = 0x02, + DAC960_V1_TwoChannelBoard = 0x03, + DAC960_V1_ThreeChannelASIC_DAC = 0x04 } __attribute__ ((packed)) Model; /* Byte 2 */ enum { - DAC960_EISA_Controller = 0x01, - DAC960_MicroChannel_Controller = 0x02, - DAC960_PCI_Controller = 0x03, - DAC960_SCSItoSCSI_Controller = 0x08 + DAC960_V1_EISA_Controller = 0x01, + DAC960_V1_MicroChannel_Controller = 0x02, + DAC960_V1_PCI_Controller = 0x03, + DAC960_V1_SCSItoSCSI_Controller = 0x08 } __attribute__ ((packed)) ProductFamily; /* Byte 3 */ } HardwareID; /* Bytes 0-3 */ /* MajorVersion.MinorVersion-FirmwareType-TurnID */ @@ -321,14 +450,14 @@ typedef struct DAC960_Enquiry2 unsigned int NonVolatileMemorySize; /* Bytes 36-39 */ struct { enum { - DAC960_DRAM = 0x00, - DAC960_EDO = 0x01, - DAC960_SDRAM = 0x02 + DAC960_V1_DRAM = 0x0, + DAC960_V1_EDO = 0x1, + DAC960_V1_SDRAM = 0x2 } __attribute__ ((packed)) RamType:3; /* Byte 40 Bits 0-2 */ enum { - DAC960_None = 0x00, - DAC960_Parity = 0x01, - DAC960_ECC = 0x02 + DAC960_V1_None = 0x0, + DAC960_V1_Parity = 0x1, + DAC960_V1_ECC = 0x2 } __attribute__ ((packed)) ErrorCorrection:3; /* Byte 40 Bits 3-5 */ boolean FastPageMode:1; /* Byte 40 Bit 6 */ boolean LowPowerMemory:1; /* Byte 40 Bit 7 */ @@ -367,14 +496,14 @@ typedef struct DAC960_Enquiry2 unsigned short CacheLineSize; /* Bytes 104-105 */ struct { enum { - DAC960_Narrow_8bit = 0x00, - DAC960_Wide_16bit = 0x01, - DAC960_Wide_32bit = 0x02 + DAC960_V1_Narrow_8bit = 0x0, + DAC960_V1_Wide_16bit = 0x1, + DAC960_V1_Wide_32bit = 0x2 } __attribute__ ((packed)) BusWidth:2; /* Byte 106 Bits 0-1 */ enum { - DAC960_Fast = 0x00, - DAC960_Ultra = 0x01, - DAC960_Ultra2 = 0x02 + DAC960_V1_Fast = 0x0, + DAC960_V1_Ultra = 0x1, + DAC960_V1_Ultra2 = 0x2 } __attribute__ ((packed)) BusSpeed:2; /* Byte 106 Bits 2-3 */ boolean Differential:1; /* Byte 106 Bit 4 */ unsigned char :3; /* Byte 106 Bits 5-7 */ @@ -383,12 +512,12 @@ typedef struct DAC960_Enquiry2 unsigned int :32; /* Bytes 108-111 */ unsigned short FirmwareBuildNumber; /* Bytes 112-113 */ enum { - DAC960_AEMI = 0x01, - DAC960_OEM1 = 0x02, - DAC960_OEM2 = 0x04, - DAC960_OEM3 = 0x08, - DAC960_Conner = 0x10, - DAC960_SAFTE = 0x20 + DAC960_V1_AEMI = 0x01, + DAC960_V1_OEM1 = 0x02, + DAC960_V1_OEM2 = 0x04, + DAC960_V1_OEM3 = 0x08, + DAC960_V1_Conner = 0x10, + DAC960_V1_SAFTE = 0x20 } __attribute__ ((packed)) FaultManagementType; /* Byte 114 */ unsigned char :8; /* Byte 115 */ struct { @@ -399,55 +528,64 @@ typedef struct DAC960_Enquiry2 unsigned int :32; /* Bytes 120-123 */ unsigned int :32; /* Bytes 124-127 */ } -DAC960_Enquiry2_T; +DAC960_V1_Enquiry2_T; /* - Define the Logical Drive State type. + Define the DAC960 V1 Firmware Logical Drive State type. */ typedef enum { - DAC960_LogicalDrive_Online = 0x03, - DAC960_LogicalDrive_Critical = 0x04, - DAC960_LogicalDrive_Offline = 0xFF + DAC960_V1_LogicalDrive_Online = 0x03, + DAC960_V1_LogicalDrive_Critical = 0x04, + DAC960_V1_LogicalDrive_Offline = 0xFF } __attribute__ ((packed)) -DAC960_LogicalDriveState_T; +DAC960_V1_LogicalDriveState_T; /* - Define the Get Logical Drive Information reply structure. + Define the DAC960 V1 Firmware Logical Drive Information structure. */ -typedef struct DAC960_LogicalDriveInformation +typedef struct DAC960_V1_LogicalDriveInformation { unsigned int LogicalDriveSize; /* Bytes 0-3 */ - DAC960_LogicalDriveState_T LogicalDriveState; /* Byte 4 */ + DAC960_V1_LogicalDriveState_T LogicalDriveState; /* Byte 4 */ unsigned char RAIDLevel:7; /* Byte 5 Bits 0-6 */ boolean WriteBack:1; /* Byte 5 Bit 7 */ - unsigned int :16; /* Bytes 6-7 */ + unsigned short :16; /* Bytes 6-7 */ } -DAC960_LogicalDriveInformation_T; +DAC960_V1_LogicalDriveInformation_T; + + +/* + Define the DAC960 V1 Firmware Get Logical Drive Information Command + reply structure. +*/ + +typedef DAC960_V1_LogicalDriveInformation_T + DAC960_V1_LogicalDriveInformationArray_T[DAC960_MaxLogicalDrives]; /* - Define the Perform Event Log Operation Types. + Define the DAC960 V1 Firmware Perform Event Log Operation Types. */ typedef enum { - DAC960_GetEventLogEntry = 0x00 + DAC960_V1_GetEventLogEntry = 0x00 } __attribute__ ((packed)) -DAC960_PerformEventLogOpType_T; +DAC960_V1_PerformEventLogOpType_T; /* - Define the Get Event Log Entry reply structure. + Define the DAC960 V1 Firmware Get Event Log Entry Command reply structure. */ -typedef struct DAC960_EventLogEntry +typedef struct DAC960_V1_EventLogEntry { unsigned char MessageType; /* Byte 0 */ unsigned char MessageLength; /* Byte 1 */ @@ -459,7 +597,7 @@ typedef struct DAC960_EventLogEntry unsigned char ErrorCode:7; /* Byte 6 Bits 0-6 */ boolean Valid:1; /* Byte 6 Bit 7 */ unsigned char SegmentNumber; /* Byte 7 */ - unsigned char SenseKey:4; /* Byte 8 Bits 0-3 */ + DAC960_SCSI_RequestSenseKey_T SenseKey:4; /* Byte 8 Bits 0-3 */ unsigned char :1; /* Byte 8 Bit 4 */ boolean ILI:1; /* Byte 8 Bit 5 */ boolean EOM:1; /* Byte 8 Bit 6 */ @@ -471,37 +609,37 @@ typedef struct DAC960_EventLogEntry unsigned char AdditionalSenseCodeQualifier; /* Byte 19 */ unsigned char Dummy[12]; /* Bytes 20-31 */ } -DAC960_EventLogEntry_T; +DAC960_V1_EventLogEntry_T; /* - Define the Physical Device State type. + Define the DAC960 V1 Firmware Physical Device State type. */ typedef enum { - DAC960_Device_Dead = 0x00, - DAC960_Device_WriteOnly = 0x02, - DAC960_Device_Online = 0x03, - DAC960_Device_Standby = 0x10 + DAC960_V1_Device_Dead = 0x00, + DAC960_V1_Device_WriteOnly = 0x02, + DAC960_V1_Device_Online = 0x03, + DAC960_V1_Device_Standby = 0x10 } __attribute__ ((packed)) -DAC960_PhysicalDeviceState_T; +DAC960_V1_PhysicalDeviceState_T; /* - Define the Get Device State reply structure. + Define the DAC960 V1 Firmware Get Device State Command reply structure. */ -typedef struct DAC960_DeviceState +typedef struct DAC960_V1_DeviceState { boolean Present:1; /* Byte 0 Bit 0 */ unsigned char :7; /* Byte 0 Bits 1-7 */ enum { - DAC960_OtherType = 0x00, - DAC960_DiskType = 0x01, - DAC960_SequentialType = 0x02, - DAC960_CDROM_or_WORM_Type = 0x03 + DAC960_V1_OtherType = 0x0, + DAC960_V1_DiskType = 0x1, + DAC960_V1_SequentialType = 0x2, + DAC960_V1_CDROM_or_WORM_Type = 0x3 } __attribute__ ((packed)) DeviceType:2; /* Byte 1 Bits 0-1 */ boolean :1; /* Byte 1 Bit 2 */ boolean Fast20:1; /* Byte 1 Bit 3 */ @@ -509,60 +647,60 @@ typedef struct DAC960_DeviceState boolean Fast:1; /* Byte 1 Bit 5 */ boolean Wide:1; /* Byte 1 Bit 6 */ boolean TaggedQueuingSupported:1; /* Byte 1 Bit 7 */ - DAC960_PhysicalDeviceState_T DeviceState; /* Byte 2 */ + DAC960_V1_PhysicalDeviceState_T DeviceState; /* Byte 2 */ unsigned char :8; /* Byte 3 */ unsigned char SynchronousMultiplier; /* Byte 4 */ unsigned char SynchronousOffset:5; /* Byte 5 Bits 0-4 */ unsigned char :3; /* Byte 5 Bits 5-7 */ unsigned int DiskSize __attribute__ ((packed)); /* Bytes 6-9 */ } -DAC960_DeviceState_T; +DAC960_V1_DeviceState_T; /* - Define the Get Rebuild Progress reply structure. + Define the DAC960 V1 Firmware Get Rebuild Progress Command reply structure. */ -typedef struct DAC960_RebuildProgress +typedef struct DAC960_V1_RebuildProgress { unsigned int LogicalDriveNumber; /* Bytes 0-3 */ unsigned int LogicalDriveSize; /* Bytes 4-7 */ unsigned int RemainingBlocks; /* Bytes 8-11 */ } -DAC960_RebuildProgress_T; +DAC960_V1_RebuildProgress_T; /* - Define the Error Table Entry and Get Error Table reply structure. + Define the DAC960 V1 Firmware Error Table Entry structure. */ -typedef struct DAC960_ErrorTableEntry +typedef struct DAC960_V1_ErrorTableEntry { unsigned char ParityErrorCount; /* Byte 0 */ unsigned char SoftErrorCount; /* Byte 1 */ unsigned char HardErrorCount; /* Byte 2 */ unsigned char MiscErrorCount; /* Byte 3 */ } -DAC960_ErrorTableEntry_T; +DAC960_V1_ErrorTableEntry_T; /* - Define the Get Error Table reply structure. + Define the DAC960 V1 Firmware Get Error Table Command reply structure. */ -typedef struct DAC960_ErrorTable +typedef struct DAC960_V1_ErrorTable { - DAC960_ErrorTableEntry_T - ErrorTableEntries[DAC960_MaxChannels][DAC960_MaxTargets]; + DAC960_V1_ErrorTableEntry_T + ErrorTableEntries[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets]; } -DAC960_ErrorTable_T; +DAC960_V1_ErrorTable_T; /* - Define the Config2 reply structure. + Define the DAC960 V1 Firmware Read Config2 Command reply structure. */ -typedef struct DAC960_Config2 +typedef struct DAC960_V1_Config2 { unsigned char :1; /* Byte 0 Bit 0 */ boolean ActiveNegationEnabled:1; /* Byte 0 Bit 1 */ @@ -576,12 +714,12 @@ typedef struct DAC960_Config2 boolean AEMI_OFM:1; /* Byte 1 Bit 6 */ unsigned char :1; /* Byte 1 Bit 7 */ enum { - DAC960_OEMID_Mylex = 0x00, - DAC960_OEMID_IBM = 0x08, - DAC960_OEMID_HP = 0x0A, - DAC960_OEMID_DEC = 0x0C, - DAC960_OEMID_Siemens = 0x10, - DAC960_OEMID_Intel = 0x12 + DAC960_V1_OEMID_Mylex = 0x00, + DAC960_V1_OEMID_IBM = 0x08, + DAC960_V1_OEMID_HP = 0x0A, + DAC960_V1_OEMID_DEC = 0x0C, + DAC960_V1_OEMID_Siemens = 0x10, + DAC960_V1_OEMID_Intel = 0x12 } __attribute__ ((packed)) OEMID; /* Byte 2 */ unsigned char OEMModelNumber; /* Byte 3 */ unsigned char PhysicalSector; /* Byte 4 */ @@ -600,21 +738,21 @@ typedef struct DAC960_Config2 unsigned char BlocksPerStripe; /* Byte 11 */ struct { enum { - DAC960_Async = 0x00, - DAC960_Sync_8MHz = 0x01, - DAC960_Sync_5MHz = 0x02, - DAC960_Sync_10or20MHz = 0x03 /* Bits 0-1 */ + DAC960_V1_Async = 0x0, + DAC960_V1_Sync_8MHz = 0x1, + DAC960_V1_Sync_5MHz = 0x2, + DAC960_V1_Sync_10or20MHz = 0x3 /* Byte 11 Bits 0-1 */ } __attribute__ ((packed)) Speed:2; - boolean Force8Bit:1; /* Bit 2 */ - boolean DisableFast20:1; /* Bit 3 */ - unsigned char :3; /* Bits 4-6 */ - boolean EnableTaggedQueuing:1; /* Bit 7 */ + boolean Force8Bit:1; /* Byte 11 Bit 2 */ + boolean DisableFast20:1; /* Byte 11 Bit 3 */ + unsigned char :3; /* Byte 11 Bits 4-6 */ + boolean EnableTaggedQueuing:1; /* Byte 11 Bit 7 */ } __attribute__ ((packed)) ChannelParameters[6]; /* Bytes 12-17 */ unsigned char SCSIInitiatorID; /* Byte 18 */ unsigned char :8; /* Byte 19 */ enum { - DAC960_StartupMode_ControllerSpinUp = 0x00, - DAC960_StartupMode_PowerOnSpinUp = 0x01 + DAC960_V1_StartupMode_ControllerSpinUp = 0x00, + DAC960_V1_StartupMode_PowerOnSpinUp = 0x01 } __attribute__ ((packed)) StartupMode; /* Byte 20 */ unsigned char SimultaneousDeviceSpinUpCount; /* Byte 21 */ unsigned char SecondsDelayBetweenSpinUps; /* Byte 22 */ @@ -623,44 +761,44 @@ typedef struct DAC960_Config2 boolean CDROMBootEnabled:1; /* Byte 52 Bit 1 */ unsigned char :3; /* Byte 52 Bits 2-4 */ enum { - DAC960_Geometry_128_32 = 0x00, - DAC960_Geometry_255_63 = 0x01, - DAC960_Geometry_Reserved1 = 0x02, - DAC960_Geometry_Reserved2 = 0x03 + DAC960_V1_Geometry_128_32 = 0x0, + DAC960_V1_Geometry_255_63 = 0x1, + DAC960_V1_Geometry_Reserved1 = 0x2, + DAC960_V1_Geometry_Reserved2 = 0x3 } __attribute__ ((packed)) DriveGeometry:2; /* Byte 52 Bits 5-6 */ unsigned char :1; /* Byte 52 Bit 7 */ unsigned char Reserved2[9]; /* Bytes 53-61 */ unsigned short Checksum; /* Bytes 62-63 */ } -DAC960_Config2_T; +DAC960_V1_Config2_T; /* - Define the DCDB request structure. + Define the DAC960 V1 Firmware DCDB request structure. */ -typedef struct DAC960_DCDB +typedef struct DAC960_V1_DCDB { unsigned char TargetID:4; /* Byte 0 Bits 0-3 */ unsigned char Channel:4; /* Byte 0 Bits 4-7 */ enum { - DAC960_DCDB_NoDataTransfer = 0, - DAC960_DCDB_DataTransferDeviceToSystem = 1, - DAC960_DCDB_DataTransferSystemToDevice = 2, - DAC960_DCDB_IllegalDataTransfer = 3 + DAC960_V1_DCDB_NoDataTransfer = 0, + DAC960_V1_DCDB_DataTransferDeviceToSystem = 1, + DAC960_V1_DCDB_DataTransferSystemToDevice = 2, + DAC960_V1_DCDB_IllegalDataTransfer = 3 } __attribute__ ((packed)) Direction:2; /* Byte 1 Bits 0-1 */ boolean EarlyStatus:1; /* Byte 1 Bit 2 */ unsigned char :1; /* Byte 1 Bit 3 */ enum { - DAC960_DCDB_Timeout_24_hours = 0, - DAC960_DCDB_Timeout_10_seconds = 1, - DAC960_DCDB_Timeout_60_seconds = 2, - DAC960_DCDB_Timeout_10_minutes = 3 + DAC960_V1_DCDB_Timeout_24_hours = 0, + DAC960_V1_DCDB_Timeout_10_seconds = 1, + DAC960_V1_DCDB_Timeout_60_seconds = 2, + DAC960_V1_DCDB_Timeout_10_minutes = 3 } __attribute__ ((packed)) Timeout:2; /* Byte 1 Bits 4-5 */ boolean NoAutomaticRequestSense:1; /* Byte 1 Bit 6 */ boolean DisconnectPermitted:1; /* Byte 1 Bit 7 */ unsigned short TransferLength; /* Bytes 2-3 */ - DAC960_BusAddress_T BusAddress; /* Bytes 4-7 */ + DAC960_BusAddress32_T BusAddress; /* Bytes 4-7 */ unsigned char CDBLength:4; /* Byte 8 Bits 0-3 */ unsigned char TransferLengthHigh4:4; /* Byte 8 Bits 4-7 */ unsigned char SenseLength; /* Byte 9 */ @@ -669,171 +807,988 @@ typedef struct DAC960_DCDB unsigned char Status; /* Byte 86 */ unsigned char :8; /* Byte 87 */ } -DAC960_DCDB_T; - - -/* - Define the SCSI INQUIRY Standard Data reply structure. -*/ - -typedef struct DAC960_SCSI_Inquiry -{ - unsigned char PeripheralDeviceType:5; /* Byte 0 Bits 0-4 */ - unsigned char PeripheralQualifier:3; /* Byte 0 Bits 5-7 */ - unsigned char DeviceTypeModifier:7; /* Byte 1 Bits 0-6 */ - boolean RMB:1; /* Byte 1 Bit 7 */ - unsigned char ANSI_ApprovedVersion:3; /* Byte 2 Bits 0-2 */ - unsigned char ECMA_Version:3; /* Byte 2 Bits 3-5 */ - unsigned char ISO_Version:2; /* Byte 2 Bits 6-7 */ - unsigned char ResponseDataFormat:4; /* Byte 3 Bits 0-3 */ - unsigned char :2; /* Byte 3 Bits 4-5 */ - boolean TrmIOP:1; /* Byte 3 Bit 6 */ - boolean AENC:1; /* Byte 3 Bit 7 */ - unsigned char AdditionalLength; /* Byte 4 */ - unsigned char :8; /* Byte 5 */ - unsigned char :8; /* Byte 6 */ - boolean SftRe:1; /* Byte 7 Bit 0 */ - boolean CmdQue:1; /* Byte 7 Bit 1 */ - boolean :1; /* Byte 7 Bit 2 */ - boolean Linked:1; /* Byte 7 Bit 3 */ - boolean Sync:1; /* Byte 7 Bit 4 */ - boolean WBus16:1; /* Byte 7 Bit 5 */ - boolean WBus32:1; /* Byte 7 Bit 6 */ - boolean RelAdr:1; /* Byte 7 Bit 7 */ - unsigned char VendorIdentification[8]; /* Bytes 8-15 */ - unsigned char ProductIdentification[16]; /* Bytes 16-31 */ - unsigned char ProductRevisionLevel[4]; /* Bytes 32-35 */ -} -DAC960_SCSI_Inquiry_T; - - -/* - Define the SCSI INQUIRY Unit Serial Number reply structure. -*/ - -typedef struct DAC960_SCSI_Inquiry_UnitSerialNumber -{ - unsigned char PeripheralDeviceType:5; /* Byte 0 Bits 0-4 */ - unsigned char PeripheralQualifier:3; /* Byte 0 Bits 5-7 */ - unsigned char PageCode; /* Byte 1 */ - unsigned char :8; /* Byte 2 */ - unsigned char PageLength; /* Byte 3 */ - unsigned char ProductSerialNumber[28]; /* Bytes 4 - 31 */ -} -DAC960_SCSI_Inquiry_UnitSerialNumber_T; +DAC960_V1_DCDB_T; /* - Define the Scatter/Gather List Type 1 32 Bit Address 32 Bit Byte Count - structure. + Define the DAC960 V1 Firmware Scatter/Gather List Type 1 32 Bit Address + 32 Bit Byte Count structure. */ -typedef struct DAC960_ScatterGatherSegment +typedef struct DAC960_V1_ScatterGatherSegment { - DAC960_BusAddress_T SegmentDataPointer; /* Bytes 0-3 */ - DAC960_ByteCount_T SegmentByteCount; /* Bytes 4-7 */ + DAC960_BusAddress32_T SegmentDataPointer; /* Bytes 0-3 */ + DAC960_ByteCount32_T SegmentByteCount; /* Bytes 4-7 */ } -DAC960_ScatterGatherSegment_T; +DAC960_V1_ScatterGatherSegment_T; /* - Define the 13 Byte DAC960 Command Mailbox structure. Bytes 13-15 are - not used. The Command Mailbox structure is padded to 16 bytes for + Define the 13 Byte DAC960 V1 Firmware Command Mailbox structure. Bytes 13-15 + are not used. The Command Mailbox structure is padded to 16 bytes for efficient access. */ -typedef union DAC960_CommandMailbox +typedef union DAC960_V1_CommandMailbox { unsigned int Words[4]; /* Words 0-3 */ unsigned char Bytes[16]; /* Bytes 0-15 */ struct { - DAC960_CommandOpcode_T CommandOpcode; /* Byte 0 */ - DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ + DAC960_V1_CommandOpcode_T CommandOpcode; /* Byte 0 */ + DAC960_V1_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ unsigned char Dummy[14]; /* Bytes 2-15 */ } __attribute__ ((packed)) Common; struct { - DAC960_CommandOpcode_T CommandOpcode; /* Byte 0 */ - DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ + DAC960_V1_CommandOpcode_T CommandOpcode; /* Byte 0 */ + DAC960_V1_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ unsigned char Dummy1[6]; /* Bytes 2-7 */ - DAC960_BusAddress_T BusAddress; /* Bytes 8-11 */ + DAC960_BusAddress32_T BusAddress; /* Bytes 8-11 */ unsigned char Dummy2[4]; /* Bytes 12-15 */ } __attribute__ ((packed)) Type3; struct { - DAC960_CommandOpcode_T CommandOpcode; /* Byte 0 */ - DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ + DAC960_V1_CommandOpcode_T CommandOpcode; /* Byte 0 */ + DAC960_V1_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ unsigned char Dummy1[5]; /* Bytes 2-6 */ unsigned char LogicalDriveNumber:6; /* Byte 7 Bits 0-6 */ boolean AutoRestore:1; /* Byte 7 Bit 7 */ unsigned char Dummy2[8]; /* Bytes 8-15 */ } __attribute__ ((packed)) Type3C; struct { - DAC960_CommandOpcode_T CommandOpcode; /* Byte 0 */ - DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ + DAC960_V1_CommandOpcode_T CommandOpcode; /* Byte 0 */ + DAC960_V1_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ unsigned char Channel; /* Byte 2 */ unsigned char TargetID; /* Byte 3 */ - DAC960_PhysicalDeviceState_T DeviceState:5; /* Byte 4 Bits 0-4 */ + DAC960_V1_PhysicalDeviceState_T DeviceState:5; /* Byte 4 Bits 0-4 */ unsigned char Modifier:3; /* Byte 4 Bits 5-7 */ unsigned char Dummy1[3]; /* Bytes 5-7 */ - DAC960_BusAddress_T BusAddress; /* Bytes 8-11 */ + DAC960_BusAddress32_T BusAddress; /* Bytes 8-11 */ unsigned char Dummy2[4]; /* Bytes 12-15 */ } __attribute__ ((packed)) Type3D; struct { - DAC960_CommandOpcode_T CommandOpcode; /* Byte 0 */ - DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ - DAC960_PerformEventLogOpType_T OperationType; /* Byte 2 */ + DAC960_V1_CommandOpcode_T CommandOpcode; /* Byte 0 */ + DAC960_V1_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ + DAC960_V1_PerformEventLogOpType_T OperationType; /* Byte 2 */ unsigned char OperationQualifier; /* Byte 3 */ unsigned short SequenceNumber; /* Bytes 4-5 */ unsigned char Dummy1[2]; /* Bytes 6-7 */ - DAC960_BusAddress_T BusAddress; /* Bytes 8-11 */ + DAC960_BusAddress32_T BusAddress; /* Bytes 8-11 */ unsigned char Dummy2[4]; /* Bytes 12-15 */ } __attribute__ ((packed)) Type3E; struct { - DAC960_CommandOpcode_T CommandOpcode; /* Byte 0 */ - DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ + DAC960_V1_CommandOpcode_T CommandOpcode; /* Byte 0 */ + DAC960_V1_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ unsigned char Dummy1[2]; /* Bytes 2-3 */ unsigned char RebuildRateConstant; /* Byte 4 */ unsigned char Dummy2[3]; /* Bytes 5-7 */ - DAC960_BusAddress_T BusAddress; /* Bytes 8-11 */ + DAC960_BusAddress32_T BusAddress; /* Bytes 8-11 */ unsigned char Dummy3[4]; /* Bytes 12-15 */ } __attribute__ ((packed)) Type3R; struct { - DAC960_CommandOpcode_T CommandOpcode; /* Byte 0 */ - DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ + DAC960_V1_CommandOpcode_T CommandOpcode; /* Byte 0 */ + DAC960_V1_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ unsigned short TransferLength; /* Bytes 2-3 */ unsigned int LogicalBlockAddress; /* Bytes 4-7 */ - DAC960_BusAddress_T BusAddress; /* Bytes 8-11 */ + DAC960_BusAddress32_T BusAddress; /* Bytes 8-11 */ unsigned char LogicalDriveNumber; /* Byte 12 */ unsigned char Dummy[3]; /* Bytes 13-15 */ } __attribute__ ((packed)) Type4; struct { - DAC960_CommandOpcode_T CommandOpcode; /* Byte 0 */ - DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ + DAC960_V1_CommandOpcode_T CommandOpcode; /* Byte 0 */ + DAC960_V1_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ struct { unsigned short TransferLength:11; /* Bytes 2-3 */ unsigned char LogicalDriveNumber:5; /* Byte 3 Bits 3-7 */ } __attribute__ ((packed)) LD; unsigned int LogicalBlockAddress; /* Bytes 4-7 */ - DAC960_BusAddress_T BusAddress; /* Bytes 8-11 */ + DAC960_BusAddress32_T BusAddress; /* Bytes 8-11 */ unsigned char ScatterGatherCount:6; /* Byte 12 Bits 0-5 */ enum { - DAC960_ScatterGather_32BitAddress_32BitByteCount = 0x0, - DAC960_ScatterGather_32BitAddress_16BitByteCount = 0x1, - DAC960_ScatterGather_32BitByteCount_32BitAddress = 0x2, - DAC960_ScatterGather_16BitByteCount_32BitAddress = 0x3 + DAC960_V1_ScatterGather_32BitAddress_32BitByteCount = 0x0, + DAC960_V1_ScatterGather_32BitAddress_16BitByteCount = 0x1, + DAC960_V1_ScatterGather_32BitByteCount_32BitAddress = 0x2, + DAC960_V1_ScatterGather_16BitByteCount_32BitAddress = 0x3 } __attribute__ ((packed)) ScatterGatherType:2; /* Byte 12 Bits 6-7 */ unsigned char Dummy[3]; /* Bytes 13-15 */ } __attribute__ ((packed)) Type5; struct { - DAC960_CommandOpcode_T CommandOpcode; /* Byte 0 */ - DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ + DAC960_V1_CommandOpcode_T CommandOpcode; /* Byte 0 */ + DAC960_V1_CommandIdentifier_T CommandIdentifier; /* Byte 1 */ unsigned char CommandOpcode2; /* Byte 2 */ unsigned char :8; /* Byte 3 */ - DAC960_BusAddress_T CommandMailboxesBusAddress; /* Bytes 4-7 */ - DAC960_BusAddress_T StatusMailboxesBusAddress; /* Bytes 8-11 */ + DAC960_BusAddress32_T CommandMailboxesBusAddress; /* Bytes 4-7 */ + DAC960_BusAddress32_T StatusMailboxesBusAddress; /* Bytes 8-11 */ unsigned char Dummy[4]; /* Bytes 12-15 */ } __attribute__ ((packed)) TypeX; } -DAC960_CommandMailbox_T; +DAC960_V1_CommandMailbox_T; + + +/* + Define the DAC960 V2 Firmware Command Opcodes. +*/ + +typedef enum +{ + DAC960_V2_MemCopy = 0x01, + DAC960_V2_SCSI_10_Passthru = 0x02, + DAC960_V2_SCSI_255_Passthru = 0x03, + DAC960_V2_SCSI_10 = 0x04, + DAC960_V2_SCSI_256 = 0x05, + DAC960_V2_IOCTL = 0x20 +} +__attribute__ ((packed)) +DAC960_V2_CommandOpcode_T; + + +/* + Define the DAC960 V2 Firmware IOCTL Opcodes. +*/ + +typedef enum +{ + DAC960_V2_GetControllerInfo = 0x01, + DAC960_V2_GetLogicalDeviceInfoValid = 0x03, + DAC960_V2_GetPhysicalDeviceInfoValid = 0x05, + DAC960_V2_GetHealthStatus = 0x11, + DAC960_V2_GetEvent = 0x15, + DAC960_V2_SetDeviceState = 0x82, + DAC960_V2_RebuildDeviceStart = 0x88, + DAC960_V2_RebuildDeviceStop = 0x89, + DAC960_V2_ConsistencyCheckStart = 0x8C, + DAC960_V2_ConsistencyCheckStop = 0x8D, + DAC960_V2_SetMemoryMailbox = 0x8E, + DAC960_V2_PauseDevice = 0x92, + DAC960_V2_TranslatePhysicalToLogicalDevice = 0xC5 +} +__attribute__ ((packed)) +DAC960_V2_IOCTL_Opcode_T; + + +/* + Define the DAC960 V2 Firmware Command Identifier type. +*/ + +typedef unsigned short DAC960_V2_CommandIdentifier_T; + + +/* + Define the DAC960 V2 Firmware Command Status Codes. +*/ + +#define DAC960_V2_NormalCompletion 0x00 +#define DAC960_V2_AbormalCompletion 0x02 +#define DAC960_V2_DeviceNonresponsive 0x0E + +typedef unsigned char DAC960_V2_CommandStatus_T; + + +/* + Define the DAC960 V2 Firmware Memory Type structure. +*/ + +typedef struct DAC960_V2_MemoryType +{ + enum { + DAC960_V2_MemoryType_Reserved = 0x00, + DAC960_V2_MemoryType_DRAM = 0x01, + DAC960_V2_MemoryType_EDRAM = 0x02, + DAC960_V2_MemoryType_EDO = 0x03, + DAC960_V2_MemoryType_SDRAM = 0x04 + } __attribute__ ((packed)) MemoryType:5; /* Byte 0 Bits 0-4 */ + boolean :1; /* Byte 0 Bit 5 */ + boolean MemoryParity:1; /* Byte 0 Bit 6 */ + boolean MemoryECC:1; /* Byte 0 Bit 7 */ +} +DAC960_V2_MemoryType_T; + + +/* + Define the DAC960 V2 Firmware Processor Type structure. +*/ + +typedef enum +{ + DAC960_V2_ProcessorType_i960CA = 0x01, + DAC960_V2_ProcessorType_i960RD = 0x02, + DAC960_V2_ProcessorType_i960RN = 0x03, + DAC960_V2_ProcessorType_i960RP = 0x04, + DAC960_V2_ProcessorType_NorthBay = 0x05, + DAC960_V2_ProcessorType_StrongArm = 0x06, + DAC960_V2_ProcessorType_i960RM = 0x07 +} +__attribute__ ((packed)) +DAC960_V2_ProcessorType_T; + + +/* + Define the DAC960 V2 Firmware Get Controller Info reply structure. +*/ + +typedef struct DAC960_V2_ControllerInfo +{ + unsigned char :8; /* Byte 0 */ + enum { + DAC960_V2_SCSI_Bus = 0x00, + DAC960_V2_Fibre_Bus = 0x01, + DAC960_V2_PCI_Bus = 0x03 + } __attribute__ ((packed)) BusInterfaceType; /* Byte 1 */ + enum { + DAC960_V2_DAC960E = 0x01, + DAC960_V2_DAC960M = 0x08, + DAC960_V2_DAC960PD = 0x10, + DAC960_V2_DAC960PL = 0x11, + DAC960_V2_DAC960PU = 0x12, + DAC960_V2_DAC960PE = 0x13, + DAC960_V2_DAC960PG = 0x14, + DAC960_V2_DAC960PJ = 0x15, + DAC960_V2_DAC960PTL0 = 0x16, + DAC960_V2_DAC960PR = 0x17, + DAC960_V2_DAC960PRL = 0x18, + DAC960_V2_DAC960PT = 0x19, + DAC960_V2_DAC1164P = 0x1A, + DAC960_V2_DAC960PTL1 = 0x1B, + DAC960_V2_EXR2000P = 0x1C, + DAC960_V2_EXR3000P = 0x1D, + DAC960_V2_AcceleRAID352 = 0x1E, + DAC960_V2_AcceleRAID351 = 0x1F, + DAC960_V2_DAC960S = 0x60, + DAC960_V2_DAC960SU = 0x61, + DAC960_V2_DAC960SX = 0x62, + DAC960_V2_DAC960SF = 0x63, + DAC960_V2_DAC960SS = 0x64, + DAC960_V2_DAC960FL = 0x65, + DAC960_V2_DAC960LL = 0x66, + DAC960_V2_DAC960FF = 0x67, + DAC960_V2_DAC960HP = 0x68, + DAC960_V2_RAIDBRICK = 0x69, + DAC960_V2_METEOR_FL = 0x6A, + DAC960_V2_METEOR_FF = 0x6B + } __attribute__ ((packed)) ControllerType; /* Byte 2 */ + unsigned char :8; /* Byte 3 */ + unsigned short BusInterfaceSpeedMHz; /* Bytes 4-5 */ + unsigned char BusWidthBits; /* Byte 6 */ + unsigned char Reserved1[9]; /* Bytes 7-15 */ + unsigned char BusInterfaceName[16]; /* Bytes 16-31 */ + unsigned char ControllerName[16]; /* Bytes 32-47 */ + unsigned char Reserved2[16]; /* Bytes 48-63 */ + /* Firmware Release Information */ + unsigned char FirmwareMajorVersion; /* Byte 64 */ + unsigned char FirmwareMinorVersion; /* Byte 65 */ + unsigned char FirmwareTurnNumber; /* Byte 66 */ + unsigned char FirmwareBuildNumber; /* Byte 67 */ + unsigned char FirmwareReleaseDay; /* Byte 68 */ + unsigned char FirmwareReleaseMonth; /* Byte 69 */ + unsigned char FirmwareReleaseYearHigh2Digits; /* Byte 70 */ + unsigned char FirmwareReleaseYearLow2Digits; /* Byte 71 */ + /* Hardware Release Information */ + unsigned char HardwareRevision; /* Byte 72 */ + unsigned int :24; /* Bytes 73-75 */ + unsigned char HardwareReleaseDay; /* Byte 76 */ + unsigned char HardwareReleaseMonth; /* Byte 77 */ + unsigned char HardwareReleaseYearHigh2Digits; /* Byte 78 */ + unsigned char HardwareReleaseYearLow2Digits; /* Byte 79 */ + /* Hardware Manufacturing Information */ + unsigned char ManufacturingBatchNumber; /* Byte 80 */ + unsigned char :8; /* Byte 81 */ + unsigned char ManufacturingPlantNumber; /* Byte 82 */ + unsigned char :8; /* Byte 83 */ + unsigned char HardwareManufacturingDay; /* Byte 84 */ + unsigned char HardwareManufacturingMonth; /* Byte 85 */ + unsigned char HardwareManufacturingYearHigh2Digits; /* Byte 86 */ + unsigned char HardwareManufacturingYearLow2Digits; /* Byte 87 */ + unsigned char MaximumNumberOfPDDperXLDD; /* Byte 88 */ + unsigned char MaximumNumberOfILDDperXLDD; /* Byte 89 */ + unsigned short NonvolatileMemorySizeKB; /* Bytes 90-91 */ + unsigned char MaximumNumberOfXLDD; /* Byte 92 */ + unsigned int :24; /* Bytes 93-95 */ + /* Unique Information per Controller */ + unsigned char ControllerSerialNumber[16]; /* Bytes 96-111 */ + unsigned char Reserved3[16]; /* Bytes 112-127 */ + /* Vendor Information */ + unsigned int :24; /* Bytes 128-130 */ + unsigned char OEM_Information; /* Byte 131 */ + unsigned char VendorName[16]; /* Bytes 132-147 */ + /* Other Physical/Controller/Operation Information */ + boolean BBU_Present:1; /* Byte 148 Bit 0 */ + boolean ActiveActiveClusteringMode:1; /* Byte 148 Bit 1 */ + unsigned char :6; /* Byte 148 Bits 2-7 */ + unsigned char :8; /* Byte 149 */ + unsigned short :16; /* Bytes 150-151 */ + /* Physical Device Scan Information */ + boolean PhysicalScanActive:1; /* Byte 152 Bit 0 */ + unsigned char :7; /* Byte 152 Bits 1-7 */ + unsigned char PhysicalDeviceChannelNumber; /* Byte 153 */ + unsigned char PhysicalDeviceTargetID; /* Byte 154 */ + unsigned char PhysicalDeviceLogicalUnit; /* Byte 155 */ + /* Maximum Command Data Transfer Sizes */ + unsigned short MaximumDataTransferSizeInBlocks; /* Bytes 156-157 */ + unsigned short MaximumScatterGatherEntries; /* Bytes 158-159 */ + /* Logical/Physical Device Counts */ + unsigned short LogicalDevicesPresent; /* Bytes 160-161 */ + unsigned short LogicalDevicesCritical; /* Bytes 162-163 */ + unsigned short LogicalDevicesOffline; /* Bytes 164-165 */ + unsigned short PhysicalDevicesPresent; /* Bytes 166-167 */ + unsigned short PhysicalDisksPresent; /* Bytes 168-169 */ + unsigned short PhysicalDisksCritical; /* Bytes 170-171 */ + unsigned short PhysicalDisksOffline; /* Bytes 172-173 */ + unsigned short MaximumParallelCommands; /* Bytes 174-175 */ + /* Channel and Target ID Information */ + unsigned char NumberOfPhysicalChannelsPresent; /* Byte 176 */ + unsigned char NumberOfVirtualChannelsPresent; /* Byte 177 */ + unsigned char NumberOfPhysicalChannelsPossible; /* Byte 178 */ + unsigned char NumberOfVirtualChannelsPossible; /* Byte 179 */ + unsigned char MaximumTargetsPerChannel[16]; /* Bytes 180-195 */ + unsigned char Reserved4[12]; /* Bytes 196-207 */ + /* Memory/Cache Information */ + unsigned short MemorySizeMB; /* Bytes 208-209 */ + unsigned short CacheSizeMB; /* Bytes 210-211 */ + unsigned int ValidCacheSizeInBytes; /* Bytes 212-215 */ + unsigned int DirtyCacheSizeInBytes; /* Bytes 216-219 */ + unsigned short MemorySpeedMHz; /* Bytes 220-221 */ + unsigned char MemoryDataWidthBits; /* Byte 222 */ + DAC960_V2_MemoryType_T MemoryType; /* Byte 223 */ + unsigned char CacheMemoryTypeName[16]; /* Bytes 224-239 */ + /* Execution Memory Information */ + unsigned short ExecutionMemorySizeMB; /* Bytes 240-241 */ + unsigned short ExecutionL2CacheSizeMB; /* Bytes 242-243 */ + unsigned char Reserved5[8]; /* Bytes 244-251 */ + unsigned short ExecutionMemorySpeedMHz; /* Bytes 252-253 */ + unsigned char ExecutionMemoryDataWidthBits; /* Byte 254 */ + DAC960_V2_MemoryType_T ExecutionMemoryType; /* Byte 255 */ + unsigned char ExecutionMemoryTypeName[16]; /* Bytes 256-271 */ + /* First CPU Type Information */ + unsigned short FirstProcessorSpeedMHz; /* Bytes 272-273 */ + DAC960_V2_ProcessorType_T FirstProcessorType; /* Byte 274 */ + unsigned char FirstProcessorCount; /* Byte 275 */ + unsigned char Reserved6[12]; /* Bytes 276-287 */ + unsigned char FirstProcessorName[16]; /* Bytes 288-303 */ + /* Second CPU Type Information */ + unsigned short SecondProcessorSpeedMHz; /* Bytes 304-305 */ + DAC960_V2_ProcessorType_T SecondProcessorType; /* Byte 306 */ + unsigned char SecondProcessorCount; /* Byte 307 */ + unsigned char Reserved7[12]; /* Bytes 308-319 */ + unsigned char SecondProcessorName[16]; /* Bytes 320-335 */ + /* Debugging/Profiling/Command Time Tracing Information */ + unsigned short CurrentProfilingDataPageNumber; /* Bytes 336-337 */ + unsigned short ProgramsAwaitingProfilingData; /* Bytes 338-339 */ + unsigned short CurrentCommandTimeTraceDataPageNumber; /* Bytes 340-341 */ + unsigned short ProgramsAwaitingCommandTimeTraceData; /* Bytes 342-343 */ + unsigned char Reserved8[8]; /* Bytes 344-351 */ + /* Error Counters on Physical Devices */ + unsigned short PhysicalDeviceBusResets; /* Bytes 352-353 */ + unsigned short PhysicalDeviceParityErrors; /* Bytes 355-355 */ + unsigned short PhysicalDeviceSoftErrors; /* Bytes 356-357 */ + unsigned short PhysicalDeviceCommandsFailed; /* Bytes 358-359 */ + unsigned short PhysicalDeviceMiscellaneousErrors; /* Bytes 360-361 */ + unsigned short PhysicalDeviceCommandTimeouts; /* Bytes 362-363 */ + unsigned short PhysicalDeviceSelectionTimeouts; /* Bytes 364-365 */ + unsigned short PhysicalDeviceRetriesDone; /* Bytes 366-367 */ + unsigned short PhysicalDeviceAbortsDone; /* Bytes 368-369 */ + unsigned short PhysicalDeviceHostCommandAbortsDone; /* Bytes 370-371 */ + unsigned short PhysicalDevicePredictedFailuresDetected; /* Bytes 372-373 */ + unsigned short PhysicalDeviceHostCommandsFailed; /* Bytes 374-375 */ + unsigned char Reserved9[8]; /* Bytes 376-383 */ + /* Error Counters on Logical Devices */ + unsigned short LogicalDeviceSoftErrors; /* Bytes 384-385 */ + unsigned short LogicalDeviceCommandsFailed; /* Bytes 386-387 */ + unsigned short LogicalDeviceHostCommandAbortsDone; /* Bytes 388-389 */ + unsigned short :16; /* Bytes 390-391 */ + unsigned short ControllerMemoryErrors; /* Bytes 392-393 */ + unsigned short ControllerHostCommandAbortsDone; /* Bytes 394-395 */ + unsigned int :32; /* Bytes 396-399 */ + /* Long Duration Activity Information */ + unsigned short BackgroundInitializationsActive; /* Bytes 400-401 */ + unsigned short LogicalDeviceInitializationsActive; /* Bytes 402-403 */ + unsigned short PhysicalDeviceInitializationsActive; /* Bytes 404-405 */ + unsigned short ConsistencyChecksActive; /* Bytes 406-407 */ + unsigned short RebuildsActive; /* Bytes 408-409 */ + unsigned short OnlineExpansionsActive; /* Bytes 410-411 */ + unsigned short PatrolActivitiesActive; /* Bytes 412-413 */ + unsigned char LongOperationStatus; /* Byte 414 */ + unsigned char :8; /* Byte 415 */ + /* Flash ROM Information */ + unsigned char FlashType; /* Byte 416 */ + unsigned char :8; /* Byte 417 */ + unsigned short FlashSizeMB; /* Bytes 418-419 */ + unsigned int FlashLimit; /* Bytes 420-423 */ + unsigned int FlashCount; /* Bytes 424-427 */ + unsigned int :32; /* Bytes 428-431 */ + unsigned char FlashTypeName[16]; /* Bytes 432-447 */ + /* Firmware Run Time Information */ + unsigned char RebuildRate; /* Byte 448 */ + unsigned char BackgroundInitializationRate; /* Byte 449 */ + unsigned char ForegroundInitializationRate; /* Byte 450 */ + unsigned char ConsistencyCheckRate; /* Byte 451 */ + unsigned int :32; /* Bytes 452-455 */ + unsigned int MaximumDP; /* Bytes 456-459 */ + unsigned int FreeDP; /* Bytes 460-463 */ + unsigned int MaximumIOP; /* Bytes 464-467 */ + unsigned int FreeIOP; /* Bytes 468-471 */ + unsigned short MaximumCombLengthInBlocks; /* Bytes 472-473 */ + unsigned short NumberOfConfigurationGroups; /* Bytes 474-475 */ + boolean InstallationAbortStatus:1; /* Byte 476 Bit 0 */ + boolean MaintenanceModeStatus:1; /* Byte 476 Bit 1 */ + unsigned int :6; /* Byte 476 Bits 2-7 */ + unsigned int :24; /* Bytes 477-479 */ + unsigned char Reserved10[32]; /* Bytes 480-511 */ + unsigned char Reserved11[512]; /* Bytes 512-1023 */ +} +DAC960_V2_ControllerInfo_T; + + +/* + Define the DAC960 V2 Firmware Logical Device State type. +*/ + +typedef enum +{ + DAC960_V2_LogicalDevice_Online = 0x01, + DAC960_V2_LogicalDevice_Offline = 0x08, + DAC960_V2_LogicalDevice_Critical = 0x09 +} +__attribute__ ((packed)) +DAC960_V2_LogicalDeviceState_T; + + +/* + Define the DAC960 V2 Firmware Get Logical Device Info reply structure. +*/ + +typedef struct DAC960_V2_LogicalDeviceInfo +{ + unsigned char :8; /* Byte 0 */ + unsigned char Channel; /* Byte 1 */ + unsigned char TargetID; /* Byte 2 */ + unsigned char LogicalUnit; /* Byte 3 */ + DAC960_V2_LogicalDeviceState_T LogicalDeviceState; /* Byte 4 */ + unsigned char RAIDLevel; /* Byte 5 */ + unsigned char StripeSize; /* Byte 6 */ + unsigned char CacheLineSize; /* Byte 7 */ + struct { + enum { + DAC960_V2_ReadCacheDisabled = 0x0, + DAC960_V2_ReadCacheEnabled = 0x1, + DAC960_V2_ReadAheadEnabled = 0x2, + DAC960_V2_IntelligentReadAheadEnabled = 0x3 + } __attribute__ ((packed)) ReadCache:3; /* Byte 8 Bits 0-2 */ + enum { + DAC960_V2_WriteCacheDisabled = 0x0, + DAC960_V2_LogicalDeviceReadOnly = 0x1, + DAC960_V2_WriteCacheEnabled = 0x2, + DAC960_V2_IntelligentWriteCacheEnabled = 0x3 + } __attribute__ ((packed)) WriteCache:3; /* Byte 8 Bits 3-5 */ + boolean :1; /* Byte 8 Bit 6 */ + boolean LogicalDeviceInitialized:1; /* Byte 8 Bit 7 */ + } LogicalDeviceControl; /* Byte 8 */ + /* Logical Device Operations Status */ + boolean ConsistencyCheckInProgress:1; /* Byte 9 Bit 0 */ + boolean RebuildInProgress:1; /* Byte 9 Bit 1 */ + boolean BackgroundInitializationInProgress:1; /* Byte 9 Bit 2 */ + boolean ForegroundInitializationInProgress:1; /* Byte 9 Bit 3 */ + boolean DataMigrationInProgress:1; /* Byte 9 Bit 4 */ + boolean PatrolOperationInProgress:1; /* Byte 9 Bit 5 */ + unsigned char :2; /* Byte 9 Bits 6-7 */ + unsigned char RAID5WriteUpdate; /* Byte 10 */ + unsigned char RAID5Algorithm; /* Byte 11 */ + unsigned short LogicalDeviceNumber; /* Bytes 12-13 */ + /* BIOS Info */ + boolean BIOSDisabled:1; /* Byte 14 Bit 0 */ + boolean CDROMBootEnabled:1; /* Byte 14 Bit 1 */ + boolean DriveCoercionEnabled:1; /* Byte 14 Bit 2 */ + boolean WriteSameDisabled:1; /* Byte 14 Bit 3 */ + boolean HBA_ModeEnabled:1; /* Byte 14 Bit 4 */ + enum { + DAC960_V2_Geometry_128_32 = 0x0, + DAC960_V2_Geometry_255_63 = 0x1, + DAC960_V2_Geometry_Reserved1 = 0x2, + DAC960_V2_Geometry_Reserved2 = 0x3 + } __attribute__ ((packed)) DriveGeometry:2; /* Byte 14 Bits 5-6 */ + unsigned char :1; /* Byte 14 Bit 7 */ + unsigned char :8; /* Byte 15 */ + /* Error Counters */ + unsigned short SoftErrors; /* Bytes 16-17 */ + unsigned short CommandsFailed; /* Bytes 18-19 */ + unsigned short HostCommandAbortsDone; /* Bytes 20-21 */ + unsigned short DeferredWriteErrors; /* Bytes 22-23 */ + unsigned int :32; /* Bytes 24-27 */ + unsigned int :32; /* Bytes 28-31 */ + /* Device Size Information */ + unsigned short :16; /* Bytes 32-33 */ + unsigned short DeviceBlockSizeInBytes; /* Bytes 34-35 */ + unsigned int OriginalDeviceSizeIn512ByteBlocksOrMB; /* Bytes 36-39 */ + unsigned int ConfigurableDeviceSizeIn512ByteBlocksOrMB; /* Bytes 40-43 */ + unsigned int :32; /* Bytes 44-47 */ + unsigned char LogicalDeviceName[32]; /* Bytes 48-79 */ + unsigned char SCSI_InquiryData[36]; /* Bytes 80-115 */ + unsigned char Reserved1[12]; /* Bytes 116-127 */ + DAC960_ByteCount64_T LastReadBlockNumber; /* Bytes 128-135 */ + DAC960_ByteCount64_T LastWrittenBlockNumber; /* Bytes 136-143 */ + DAC960_ByteCount64_T ConsistencyCheckBlockNumber; /* Bytes 144-151 */ + DAC960_ByteCount64_T RebuildBlockNumber; /* Bytes 152-159 */ + DAC960_ByteCount64_T BackgroundInitializationBlockNumber; /* Bytes 160-167 */ + DAC960_ByteCount64_T ForegroundInitializationBlockNumber; /* Bytes 168-175 */ + DAC960_ByteCount64_T DataMigrationBlockNumber; /* Bytes 176-183 */ + DAC960_ByteCount64_T PatrolOperationBlockNumber; /* Bytes 184-191 */ + unsigned char Reserved2[64]; /* Bytes 192-255 */ +} +DAC960_V2_LogicalDeviceInfo_T; + + +/* + Define the DAC960 V2 Firmware Physical Device State type. +*/ + +typedef enum +{ + DAC960_V2_Device_Unconfigured = 0x00, + DAC960_V2_Device_Online = 0x01, + DAC960_V2_Device_WriteOnly = 0x03, + DAC960_V2_Device_Dead = 0x08, + DAC960_V2_Device_Standby = 0x21, + DAC960_V2_Device_InvalidState = 0xFF +} +__attribute__ ((packed)) +DAC960_V2_PhysicalDeviceState_T; + + +/* + Define the DAC960 V2 Firmware Get Physical Device Info reply structure. +*/ + +typedef struct DAC960_V2_PhysicalDeviceInfo +{ + unsigned char :8; /* Byte 0 */ + unsigned char Channel; /* Byte 1 */ + unsigned char TargetID; /* Byte 2 */ + unsigned char LogicalUnit; /* Byte 3 */ + /* Configuration Status Bits */ + boolean PhysicalDeviceFaultTolerant:1; /* Byte 4 Bit 0 */ + boolean :1; /* Byte 4 Bit 1 */ + boolean PhysicalDeviceLocalToController:1; /* Byte 4 Bit 2 */ + unsigned char :5; /* Byte 4 Bits 3-7 */ + /* Multiple Host/Controller Status Bits */ + boolean RemoteHostSystemDead:1; /* Byte 5 Bit 0 */ + boolean RemoteControllerDead:1; /* Byte 5 Bit 1 */ + unsigned char :6; /* Byte 5 Bits 2-7 */ + DAC960_V2_PhysicalDeviceState_T PhysicalDeviceState; /* Byte 6 */ + unsigned char NegotiatedDataWidthBits; /* Byte 7 */ + unsigned short NegotiatedSynchronousMegaTransfers; /* Bytes 8-9 */ + /* Multiported Physical Device Information */ + unsigned char NumberOfPortConnections; /* Byte 10 */ + unsigned char DriveAccessibilityBitmap; /* Byte 11 */ + unsigned int :32; /* Bytes 12-15 */ + unsigned char NetworkAddress[16]; /* Bytes 16-31 */ + unsigned short MaximumTags; /* Bytes 32-33 */ + /* Physical Device Operations Status */ + boolean ConsistencyCheckInProgress:1; /* Byte 34 Bit 0 */ + boolean RebuildInProgress:1; /* Byte 34 Bit 1 */ + boolean MakingDataConsistentInProgress:1; /* Byte 34 Bit 2 */ + boolean PhysicalDeviceInitializationInProgress:1; /* Byte 34 Bit 3 */ + boolean DataMigrationInProgress:1; /* Byte 34 Bit 4 */ + boolean PatrolOperationInProgress:1; /* Byte 34 Bit 5 */ + unsigned char :2; /* Byte 34 Bits 6-7 */ + unsigned char LongOperationStatus; /* Byte 35 */ + unsigned char ParityErrors; /* Byte 36 */ + unsigned char SoftErrors; /* Byte 37 */ + unsigned char HardErrors; /* Byte 38 */ + unsigned char MiscellaneousErrors; /* Byte 39 */ + unsigned char CommandTimeouts; /* Byte 40 */ + unsigned char Retries; /* Byte 41 */ + unsigned char Aborts; /* Byte 42 */ + unsigned char PredictedFailuresDetected; /* Byte 43 */ + unsigned int :32; /* Bytes 44-47 */ + unsigned short :16; /* Bytes 48-49 */ + unsigned short DeviceBlockSizeInBytes; /* Bytes 50-51 */ + unsigned int OriginalDeviceSizeIn512ByteBlocksOrMB; /* Bytes 52-55 */ + unsigned int ConfigurableDeviceSizeIn512ByteBlocksOrMB; /* Bytes 56-59 */ + unsigned int :32; /* Bytes 60-63 */ + unsigned char PhysicalDeviceName[16]; /* Bytes 64-79 */ + unsigned char Reserved1[16]; /* Bytes 80-95 */ + unsigned char Reserved2[32]; /* Bytes 96-127 */ + unsigned char SCSI_InquiryData[36]; /* Bytes 128-163 */ + unsigned char Reserved3[12]; /* Bytes 164-175 */ + unsigned char Reserved4[16]; /* Bytes 176-191 */ + DAC960_ByteCount64_T LastReadBlockNumber; /* Bytes 192-199 */ + DAC960_ByteCount64_T LastWrittenBlockNumber; /* Bytes 200-207 */ + DAC960_ByteCount64_T ConsistencyCheckBlockNumber; /* Bytes 208-215 */ + DAC960_ByteCount64_T RebuildBlockNumber; /* Bytes 216-223 */ + DAC960_ByteCount64_T MakingDataConsistentBlockNumber; /* Bytes 224-231 */ + DAC960_ByteCount64_T DeviceInitializationBlockNumber; /* Bytes 232-239 */ + DAC960_ByteCount64_T DataMigrationBlockNumber; /* Bytes 240-247 */ + DAC960_ByteCount64_T PatrolOperationBlockNumber; /* Bytes 248-255 */ + unsigned char Reserved5[256]; /* Bytes 256-511 */ +} +DAC960_V2_PhysicalDeviceInfo_T; + + +/* + Define the DAC960 V2 Firmware Health Status Buffer structure. +*/ + +typedef struct DAC960_V2_HealthStatusBuffer +{ + unsigned int MicrosecondsFromControllerStartTime; /* Bytes 0-3 */ + unsigned int MillisecondsFromControllerStartTime; /* Bytes 4-7 */ + unsigned int SecondsFrom1January1970; /* Bytes 8-11 */ + unsigned int :32; /* Bytes 12-15 */ + unsigned int StatusChangeCounter; /* Bytes 16-19 */ + unsigned int :32; /* Bytes 20-23 */ + unsigned int DebugOutputMessageBufferIndex; /* Bytes 24-27 */ + unsigned int CodedMessageBufferIndex; /* Bytes 28-31 */ + unsigned int CurrentTimeTracePageNumber; /* Bytes 32-35 */ + unsigned int CurrentProfilerPageNumber; /* Bytes 36-39 */ + unsigned int NextEventSequenceNumber; /* Bytes 40-43 */ + unsigned int :32; /* Bytes 44-47 */ + unsigned char Reserved1[16]; /* Bytes 48-63 */ + unsigned char Reserved2[64]; /* Bytes 64-127 */ +} +DAC960_V2_HealthStatusBuffer_T; + + +/* + Define the DAC960 V2 Firmware Get Event reply structure. +*/ + +typedef struct DAC960_V2_Event +{ + unsigned int EventSequenceNumber; /* Bytes 0-3 */ + unsigned int EventTime; /* Bytes 4-7 */ + unsigned int EventCode; /* Bytes 8-11 */ + unsigned char :8; /* Byte 12 */ + unsigned char Channel; /* Byte 13 */ + unsigned char TargetID; /* Byte 14 */ + unsigned char LogicalUnit; /* Byte 15 */ + unsigned int :32; /* Bytes 16-19 */ + unsigned int EventSpecificParameter; /* Bytes 20-23 */ + unsigned char RequestSenseData[40]; /* Bytes 24-63 */ +} +DAC960_V2_Event_T; + + +/* + Define the DAC960 V2 Firmware Command Control Bits structure. +*/ + +typedef struct DAC960_V2_CommandControlBits +{ + boolean ForceUnitAccess:1; /* Byte 0 Bit 0 */ + boolean DisablePageOut:1; /* Byte 0 Bit 1 */ + boolean :1; /* Byte 0 Bit 2 */ + boolean AdditionalScatterGatherListMemory:1; /* Byte 0 Bit 3 */ + boolean DataTransferControllerToHost:1; /* Byte 0 Bit 4 */ + boolean :1; /* Byte 0 Bit 5 */ + boolean NoAutoRequestSense:1; /* Byte 0 Bit 6 */ + boolean DisconnectProhibited:1; /* Byte 0 Bit 7 */ +} +DAC960_V2_CommandControlBits_T; + + +/* + Define the DAC960 V2 Firmware Command Timeout structure. +*/ + +typedef struct DAC960_V2_CommandTimeout +{ + unsigned char TimeoutValue:6; /* Byte 0 Bits 0-5 */ + enum { + DAC960_V2_TimeoutScale_Seconds = 0, + DAC960_V2_TimeoutScale_Minutes = 1, + DAC960_V2_TimeoutScale_Hours = 2, + DAC960_V2_TimeoutScale_Reserved = 3 + } __attribute__ ((packed)) TimeoutScale:2; /* Byte 0 Bits 6-7 */ +} +DAC960_V2_CommandTimeout_T; + + +/* + Define the DAC960 V2 Firmware Physical Device structure. +*/ + +typedef struct DAC960_V2_PhysicalDevice +{ + unsigned char LogicalUnit; /* Byte 0 */ + unsigned char TargetID; /* Byte 1 */ + unsigned char Channel:3; /* Byte 2 Bits 0-2 */ + unsigned char Controller:5; /* Byte 2 Bits 3-7 */ +} +__attribute__ ((packed)) +DAC960_V2_PhysicalDevice_T; + + +/* + Define the DAC960 V2 Firmware Logical Device structure. +*/ + +typedef struct DAC960_V2_LogicalDevice +{ + unsigned short LogicalDeviceNumber; /* Bytes 0-1 */ + unsigned char :3; /* Byte 2 Bits 0-2 */ + unsigned char Controller:5; /* Byte 2 Bits 3-7 */ +} +__attribute__ ((packed)) +DAC960_V2_LogicalDevice_T; + + +/* + Define the DAC960 V2 Firmware Operation Device type. +*/ + +typedef enum +{ + DAC960_V2_Physical_Device = 0x00, + DAC960_V2_RAID_Device = 0x01, + DAC960_V2_Physical_Channel = 0x02, + DAC960_V2_RAID_Channel = 0x03, + DAC960_V2_Physical_Controller = 0x04, + DAC960_V2_RAID_Controller = 0x05, + DAC960_V2_Configuration_Group = 0x10 +} +__attribute__ ((packed)) +DAC960_V2_OperationDevice_T; + + +/* + Define the DAC960 V2 Firmware Translate Physical To Logical Device structure. +*/ + +typedef struct DAC960_V2_PhysicalToLogicalDevice +{ + unsigned short LogicalDeviceNumber; /* Bytes 0-1 */ + unsigned short :16; /* Bytes 2-3 */ + unsigned char PreviousBootController; /* Byte 4 */ + unsigned char PreviousBootChannel; /* Byte 5 */ + unsigned char PreviousBootTargetID; /* Byte 6 */ + unsigned char PreviousBootLogicalUnit; /* Byte 7 */ +} +DAC960_V2_PhysicalToLogicalDevice_T; + + + +/* + Define the DAC960 V2 Firmware Scatter/Gather List Entry structure. +*/ + +typedef struct DAC960_V2_ScatterGatherSegment +{ + DAC960_BusAddress64_T SegmentDataPointer; /* Bytes 0-7 */ + DAC960_ByteCount64_T SegmentByteCount; /* Bytes 8-15 */ +} +DAC960_V2_ScatterGatherSegment_T; + + +/* + Define the DAC960 V2 Firmware Data Transfer Memory Address structure. +*/ + +typedef union DAC960_V2_DataTransferMemoryAddress +{ + DAC960_V2_ScatterGatherSegment_T ScatterGatherSegments[2]; /* Bytes 0-31 */ + struct { + unsigned short ScatterGatherList0Length; /* Bytes 0-1 */ + unsigned short ScatterGatherList1Length; /* Bytes 2-3 */ + unsigned short ScatterGatherList2Length; /* Bytes 4-5 */ + unsigned short :16; /* Bytes 6-7 */ + DAC960_BusAddress64_T ScatterGatherList0Address; /* Bytes 8-15 */ + DAC960_BusAddress64_T ScatterGatherList1Address; /* Bytes 16-23 */ + DAC960_BusAddress64_T ScatterGatherList2Address; /* Bytes 24-31 */ + } ExtendedScatterGather; +} +DAC960_V2_DataTransferMemoryAddress_T; + + +/* + Define the 64 Byte DAC960 V2 Firmware Command Mailbox structure. +*/ + +typedef union DAC960_V2_CommandMailbox +{ + unsigned int Words[16]; /* Words 0-15 */ + struct { + DAC960_V2_CommandIdentifier_T CommandIdentifier; /* Bytes 0-1 */ + DAC960_V2_CommandOpcode_T CommandOpcode; /* Byte 2 */ + DAC960_V2_CommandControlBits_T CommandControlBits; /* Byte 3 */ + DAC960_ByteCount32_T DataTransferSize:24; /* Bytes 4-6 */ + unsigned char DataTransferPageNumber; /* Byte 7 */ + DAC960_BusAddress64_T RequestSenseBusAddress; /* Bytes 8-15 */ + unsigned int :24; /* Bytes 16-18 */ + DAC960_V2_CommandTimeout_T CommandTimeout; /* Byte 19 */ + unsigned char RequestSenseSize; /* Byte 20 */ + unsigned char IOCTL_Opcode; /* Byte 21 */ + unsigned char Reserved[10]; /* Bytes 22-31 */ + DAC960_V2_DataTransferMemoryAddress_T + DataTransferMemoryAddress; /* Bytes 32-63 */ + } Common; + struct { + DAC960_V2_CommandIdentifier_T CommandIdentifier; /* Bytes 0-1 */ + DAC960_V2_CommandOpcode_T CommandOpcode; /* Byte 2 */ + DAC960_V2_CommandControlBits_T CommandControlBits; /* Byte 3 */ + DAC960_ByteCount32_T DataTransferSize:24; /* Bytes 4-6 */ + unsigned char DataTransferPageNumber; /* Byte 7 */ + DAC960_BusAddress64_T RequestSenseBusAddress; /* Bytes 8-15 */ + DAC960_V2_PhysicalDevice_T PhysicalDevice; /* Bytes 16-18 */ + DAC960_V2_CommandTimeout_T CommandTimeout; /* Byte 19 */ + unsigned char RequestSenseSize; /* Byte 20 */ + unsigned char CDBLength; /* Byte 21 */ + unsigned char SCSI_CDB[10]; /* Bytes 22-31 */ + DAC960_V2_DataTransferMemoryAddress_T + DataTransferMemoryAddress; /* Bytes 32-63 */ + } SCSI_10; + struct { + DAC960_V2_CommandIdentifier_T CommandIdentifier; /* Bytes 0-1 */ + DAC960_V2_CommandOpcode_T CommandOpcode; /* Byte 2 */ + DAC960_V2_CommandControlBits_T CommandControlBits; /* Byte 3 */ + DAC960_ByteCount32_T DataTransferSize:24; /* Bytes 4-6 */ + unsigned char DataTransferPageNumber; /* Byte 7 */ + DAC960_BusAddress64_T RequestSenseBusAddress; /* Bytes 8-15 */ + DAC960_V2_PhysicalDevice_T PhysicalDevice; /* Bytes 16-18 */ + DAC960_V2_CommandTimeout_T CommandTimeout; /* Byte 19 */ + unsigned char RequestSenseSize; /* Byte 20 */ + unsigned char CDBLength; /* Byte 21 */ + unsigned short :16; /* Bytes 22-23 */ + DAC960_BusAddress64_T SCSI_CDB_BusAddress; /* Bytes 24-31 */ + DAC960_V2_DataTransferMemoryAddress_T + DataTransferMemoryAddress; /* Bytes 32-63 */ + } SCSI_255; + struct { + DAC960_V2_CommandIdentifier_T CommandIdentifier; /* Bytes 0-1 */ + DAC960_V2_CommandOpcode_T CommandOpcode; /* Byte 2 */ + DAC960_V2_CommandControlBits_T CommandControlBits; /* Byte 3 */ + DAC960_ByteCount32_T DataTransferSize:24; /* Bytes 4-6 */ + unsigned char DataTransferPageNumber; /* Byte 7 */ + DAC960_BusAddress64_T RequestSenseBusAddress; /* Bytes 8-15 */ + unsigned short :16; /* Bytes 16-17 */ + unsigned char ControllerNumber; /* Byte 18 */ + DAC960_V2_CommandTimeout_T CommandTimeout; /* Byte 19 */ + unsigned char RequestSenseSize; /* Byte 20 */ + unsigned char IOCTL_Opcode; /* Byte 21 */ + unsigned char Reserved[10]; /* Bytes 22-31 */ + DAC960_V2_DataTransferMemoryAddress_T + DataTransferMemoryAddress; /* Bytes 32-63 */ + } ControllerInfo; + struct { + DAC960_V2_CommandIdentifier_T CommandIdentifier; /* Bytes 0-1 */ + DAC960_V2_CommandOpcode_T CommandOpcode; /* Byte 2 */ + DAC960_V2_CommandControlBits_T CommandControlBits; /* Byte 3 */ + DAC960_ByteCount32_T DataTransferSize:24; /* Bytes 4-6 */ + unsigned char DataTransferPageNumber; /* Byte 7 */ + DAC960_BusAddress64_T RequestSenseBusAddress; /* Bytes 8-15 */ + DAC960_V2_LogicalDevice_T LogicalDevice; /* Bytes 16-18 */ + DAC960_V2_CommandTimeout_T CommandTimeout; /* Byte 19 */ + unsigned char RequestSenseSize; /* Byte 20 */ + unsigned char IOCTL_Opcode; /* Byte 21 */ + unsigned char Reserved[10]; /* Bytes 22-31 */ + DAC960_V2_DataTransferMemoryAddress_T + DataTransferMemoryAddress; /* Bytes 32-63 */ + } LogicalDeviceInfo; + struct { + DAC960_V2_CommandIdentifier_T CommandIdentifier; /* Bytes 0-1 */ + DAC960_V2_CommandOpcode_T CommandOpcode; /* Byte 2 */ + DAC960_V2_CommandControlBits_T CommandControlBits; /* Byte 3 */ + DAC960_ByteCount32_T DataTransferSize:24; /* Bytes 4-6 */ + unsigned char DataTransferPageNumber; /* Byte 7 */ + DAC960_BusAddress64_T RequestSenseBusAddress; /* Bytes 8-15 */ + DAC960_V2_PhysicalDevice_T PhysicalDevice; /* Bytes 16-18 */ + DAC960_V2_CommandTimeout_T CommandTimeout; /* Byte 19 */ + unsigned char RequestSenseSize; /* Byte 20 */ + unsigned char IOCTL_Opcode; /* Byte 21 */ + unsigned char Reserved[10]; /* Bytes 22-31 */ + DAC960_V2_DataTransferMemoryAddress_T + DataTransferMemoryAddress; /* Bytes 32-63 */ + } PhysicalDeviceInfo; + struct { + DAC960_V2_CommandIdentifier_T CommandIdentifier; /* Bytes 0-1 */ + DAC960_V2_CommandOpcode_T CommandOpcode; /* Byte 2 */ + DAC960_V2_CommandControlBits_T CommandControlBits; /* Byte 3 */ + DAC960_ByteCount32_T DataTransferSize:24; /* Bytes 4-6 */ + unsigned char DataTransferPageNumber; /* Byte 7 */ + DAC960_BusAddress64_T RequestSenseBusAddress; /* Bytes 8-15 */ + unsigned short EventSequenceNumberHigh16; /* Bytes 16-17 */ + unsigned char ControllerNumber; /* Byte 18 */ + DAC960_V2_CommandTimeout_T CommandTimeout; /* Byte 19 */ + unsigned char RequestSenseSize; /* Byte 20 */ + unsigned char IOCTL_Opcode; /* Byte 21 */ + unsigned short EventSequenceNumberLow16; /* Bytes 22-23 */ + unsigned char Reserved[8]; /* Bytes 24-31 */ + DAC960_V2_DataTransferMemoryAddress_T + DataTransferMemoryAddress; /* Bytes 32-63 */ + } GetEvent; + struct { + DAC960_V2_CommandIdentifier_T CommandIdentifier; /* Bytes 0-1 */ + DAC960_V2_CommandOpcode_T CommandOpcode; /* Byte 2 */ + DAC960_V2_CommandControlBits_T CommandControlBits; /* Byte 3 */ + DAC960_ByteCount32_T DataTransferSize:24; /* Bytes 4-6 */ + unsigned char DataTransferPageNumber; /* Byte 7 */ + DAC960_BusAddress64_T RequestSenseBusAddress; /* Bytes 8-15 */ + DAC960_V2_LogicalDevice_T LogicalDevice; /* Bytes 16-18 */ + DAC960_V2_CommandTimeout_T CommandTimeout; /* Byte 19 */ + unsigned char RequestSenseSize; /* Byte 20 */ + unsigned char IOCTL_Opcode; /* Byte 21 */ + union { + DAC960_V2_LogicalDeviceState_T LogicalDeviceState; + DAC960_V2_PhysicalDeviceState_T PhysicalDeviceState; + } DeviceState; /* Byte 22 */ + unsigned char Reserved[9]; /* Bytes 23-31 */ + DAC960_V2_DataTransferMemoryAddress_T + DataTransferMemoryAddress; /* Bytes 32-63 */ + } SetDeviceState; + struct { + DAC960_V2_CommandIdentifier_T CommandIdentifier; /* Bytes 0-1 */ + DAC960_V2_CommandOpcode_T CommandOpcode; /* Byte 2 */ + DAC960_V2_CommandControlBits_T CommandControlBits; /* Byte 3 */ + DAC960_ByteCount32_T DataTransferSize:24; /* Bytes 4-6 */ + unsigned char DataTransferPageNumber; /* Byte 7 */ + DAC960_BusAddress64_T RequestSenseBusAddress; /* Bytes 8-15 */ + DAC960_V2_LogicalDevice_T LogicalDevice; /* Bytes 16-18 */ + DAC960_V2_CommandTimeout_T CommandTimeout; /* Byte 19 */ + unsigned char RequestSenseSize; /* Byte 20 */ + unsigned char IOCTL_Opcode; /* Byte 21 */ + boolean RestoreConsistency:1; /* Byte 22 Bit 0 */ + boolean InitializedAreaOnly:1; /* Byte 22 Bit 1 */ + unsigned char :6; /* Byte 22 Bits 2-7 */ + unsigned char Reserved[9]; /* Bytes 23-31 */ + DAC960_V2_DataTransferMemoryAddress_T + DataTransferMemoryAddress; /* Bytes 32-63 */ + } ConsistencyCheck; + struct { + DAC960_V2_CommandIdentifier_T CommandIdentifier; /* Bytes 0-1 */ + DAC960_V2_CommandOpcode_T CommandOpcode; /* Byte 2 */ + DAC960_V2_CommandControlBits_T CommandControlBits; /* Byte 3 */ + unsigned char FirstCommandMailboxSizeKB; /* Byte 4 */ + unsigned char FirstStatusMailboxSizeKB; /* Byte 5 */ + unsigned char SecondCommandMailboxSizeKB; /* Byte 6 */ + unsigned char SecondStatusMailboxSizeKB; /* Byte 7 */ + DAC960_BusAddress64_T RequestSenseBusAddress; /* Bytes 8-15 */ + unsigned int :24; /* Bytes 16-18 */ + DAC960_V2_CommandTimeout_T CommandTimeout; /* Byte 19 */ + unsigned char RequestSenseSize; /* Byte 20 */ + unsigned char IOCTL_Opcode; /* Byte 21 */ + unsigned char HealthStatusBufferSizeKB; /* Byte 22 */ + unsigned char :8; /* Byte 23 */ + DAC960_BusAddress64_T HealthStatusBufferBusAddress; /* Bytes 24-31 */ + DAC960_BusAddress64_T FirstCommandMailboxBusAddress; /* Bytes 32-39 */ + DAC960_BusAddress64_T FirstStatusMailboxBusAddress; /* Bytes 40-47 */ + DAC960_BusAddress64_T SecondCommandMailboxBusAddress; /* Bytes 48-55 */ + DAC960_BusAddress64_T SecondStatusMailboxBusAddress; /* Bytes 56-63 */ + } SetMemoryMailbox; + struct { + DAC960_V2_CommandIdentifier_T CommandIdentifier; /* Bytes 0-1 */ + DAC960_V2_CommandOpcode_T CommandOpcode; /* Byte 2 */ + DAC960_V2_CommandControlBits_T CommandControlBits; /* Byte 3 */ + DAC960_ByteCount32_T DataTransferSize:24; /* Bytes 4-6 */ + unsigned char DataTransferPageNumber; /* Byte 7 */ + DAC960_BusAddress64_T RequestSenseBusAddress; /* Bytes 8-15 */ + DAC960_V2_PhysicalDevice_T PhysicalDevice; /* Bytes 16-18 */ + DAC960_V2_CommandTimeout_T CommandTimeout; /* Byte 19 */ + unsigned char RequestSenseSize; /* Byte 20 */ + unsigned char IOCTL_Opcode; /* Byte 21 */ + DAC960_V2_OperationDevice_T OperationDevice; /* Byte 22 */ + unsigned char Reserved[9]; /* Bytes 23-31 */ + DAC960_V2_DataTransferMemoryAddress_T + DataTransferMemoryAddress; /* Bytes 32-63 */ + } DeviceOperation; +} +__attribute__ ((packed)) +DAC960_V2_CommandMailbox_T; /* @@ -842,7 +1797,9 @@ DAC960_CommandMailbox_T; #define DAC960_IOCTL_GET_CONTROLLER_COUNT 0xDAC001 #define DAC960_IOCTL_GET_CONTROLLER_INFO 0xDAC002 -#define DAC960_IOCTL_EXECUTE_COMMAND 0xDAC003 +#define DAC960_IOCTL_V1_EXECUTE_COMMAND 0xDAC003 +#define DAC960_IOCTL_V2_EXECUTE_COMMAND 0xDAC004 +#define DAC960_IOCTL_V2_GET_HEALTH_STATUS 0xDAC005 /* @@ -852,49 +1809,98 @@ DAC960_CommandMailbox_T; typedef struct DAC960_ControllerInfo { unsigned char ControllerNumber; + unsigned char FirmwareType; + unsigned char Channels; + unsigned char Targets; unsigned char PCI_Bus; unsigned char PCI_Device; unsigned char PCI_Function; unsigned char IRQ_Channel; - unsigned char Channels; DAC960_PCI_Address_T PCI_Address; - unsigned char ModelName[16]; - unsigned char FirmwareVersion[16]; + unsigned char ModelName[20]; + unsigned char FirmwareVersion[12]; } DAC960_ControllerInfo_T; /* - Define the User Mode DAC960_IOCTL_EXECUTE_COMMAND request structure. + Define the User Mode DAC960_IOCTL_V1_EXECUTE_COMMAND request structure. */ -typedef struct DAC960_UserCommand +typedef struct DAC960_V1_UserCommand { unsigned char ControllerNumber; - DAC960_CommandMailbox_T CommandMailbox; + DAC960_V1_CommandMailbox_T CommandMailbox; int DataTransferLength; void *DataTransferBuffer; - DAC960_DCDB_T *DCDB; + DAC960_V1_DCDB_T *DCDB; } -DAC960_UserCommand_T; +DAC960_V1_UserCommand_T; /* - Define the Kernel Mode DAC960_IOCTL_EXECUTE_COMMAND request structure. + Define the Kernel Mode DAC960_IOCTL_V1_EXECUTE_COMMAND request structure. */ -typedef struct DAC960_KernelCommand +typedef struct DAC960_V1_KernelCommand { unsigned char ControllerNumber; - DAC960_CommandMailbox_T CommandMailbox; + DAC960_V1_CommandMailbox_T CommandMailbox; int DataTransferLength; void *DataTransferBuffer; - DAC960_DCDB_T *DCDB; - DAC960_CommandStatus_T CommandStatus; - void (*CompletionFunction)(struct DAC960_KernelCommand *); + DAC960_V1_DCDB_T *DCDB; + DAC960_V1_CommandStatus_T CommandStatus; + void (*CompletionFunction)(struct DAC960_V1_KernelCommand *); void *CompletionData; } -DAC960_KernelCommand_T; +DAC960_V1_KernelCommand_T; + + +/* + Define the User Mode DAC960_IOCTL_V2_EXECUTE_COMMAND request structure. +*/ + +typedef struct DAC960_V2_UserCommand +{ + unsigned char ControllerNumber; + DAC960_V2_CommandMailbox_T CommandMailbox; + int DataTransferLength; + int RequestSenseLength; + void *DataTransferBuffer; + void *RequestSenseBuffer; +} +DAC960_V2_UserCommand_T; + + +/* + Define the Kernel Mode DAC960_IOCTL_V2_EXECUTE_COMMAND request structure. +*/ + +typedef struct DAC960_V2_KernelCommand +{ + unsigned char ControllerNumber; + DAC960_V2_CommandMailbox_T CommandMailbox; + int DataTransferLength; + int RequestSenseLength; + void *DataTransferBuffer; + void *RequestSenseBuffer; + DAC960_V2_CommandStatus_T CommandStatus; + void (*CompletionFunction)(struct DAC960_V2_KernelCommand *); + void *CompletionData; +} +DAC960_V2_KernelCommand_T; + + +/* + Define the User Mode DAC960_IOCTL_V2_GET_HEALTH_STATUS request structure. +*/ + +typedef struct DAC960_V2_GetHealthStatus +{ + unsigned char ControllerNumber; + DAC960_V2_HealthStatusBuffer_T *HealthStatusBuffer; +} +DAC960_V2_GetHealthStatus_T; /* @@ -908,9 +1914,9 @@ extern int DAC960_KernelIOCTL(unsigned int Request, void *Argument); Virtual_to_Bus maps from Kernel Virtual Addresses to PCI Bus Addresses. */ -static inline DAC960_BusAddress_T Virtual_to_Bus(void *VirtualAddress) +static inline DAC960_BusAddress32_T Virtual_to_Bus(void *VirtualAddress) { - return (DAC960_BusAddress_T) virt_to_bus(VirtualAddress); + return (DAC960_BusAddress32_T) virt_to_bus(VirtualAddress); } @@ -918,7 +1924,7 @@ static inline DAC960_BusAddress_T Virtual_to_Bus(void *VirtualAddress) Bus_to_Virtual maps from PCI Bus Addresses to Kernel Virtual Addresses. */ -static inline void *Bus_to_Virtual(DAC960_BusAddress_T BusAddress) +static inline void *Bus_to_Virtual(DAC960_BusAddress32_T BusAddress) { return (void *) bus_to_virt(BusAddress); } @@ -933,28 +1939,31 @@ static inline void *Bus_to_Virtual(DAC960_BusAddress_T BusAddress) /* Define the maximum Driver Queue Depth and Controller Queue Depth supported - by any DAC960 model. + by DAC960 V1 and V2 Firmware Controllers. */ -#define DAC960_MaxDriverQueueDepth 127 -#define DAC960_MaxControllerQueueDepth 128 +#define DAC960_MaxDriverQueueDepth 511 +#define DAC960_MaxControllerQueueDepth 512 /* - Define the maximum number of Scatter/Gather Segments supported by any - DAC960 model. + Define the maximum number of Scatter/Gather Segments supported for any + DAC960 V1 and V2 Firmware controller. */ -#define DAC960_MaxScatterGatherSegments 33 +#define DAC960_V1_ScatterGatherLimit 33 +#define DAC960_V2_ScatterGatherLimit 128 /* Define the number of Command Mailboxes and Status Mailboxes used by the - Memory Mailbox Interface. + DAC960 V1 and V2 Firmware Memory Mailbox Interface. */ -#define DAC960_CommandMailboxCount 256 -#define DAC960_StatusMailboxCount 1024 +#define DAC960_V1_CommandMailboxCount 256 +#define DAC960_V1_StatusMailboxCount 1024 +#define DAC960_V2_CommandMailboxCount 512 +#define DAC960_V2_StatusMailboxCount 512 /* @@ -972,6 +1981,13 @@ static inline void *Bus_to_Virtual(DAC960_BusAddress_T BusAddress) /* + Define the DAC960 Controller Health Status Monitoring Interval. +*/ + +#define DAC960_HealthStatusMonitoringInterval (1 * HZ) + + +/* Define the DAC960 Controller Progress Reporting Interval. */ @@ -1029,27 +2045,50 @@ static inline void *Bus_to_Virtual(DAC960_BusAddress_T BusAddress) /* - Define the Controller Line Buffer, Status Buffer, Rebuild Progress, - and User Message Sizes. + Define the number of Command structures that should be allocated as a + group to optimize kernel memory allocation. +*/ + +#define DAC960_V1_CommandAllocationGroupSize 11 +#define DAC960_V2_CommandAllocationGroupSize 29 + + +/* + Define the Controller Line Buffer, Progress Buffer, User Message, and + Initial Status Buffer sizes. */ #define DAC960_LineBufferSize 100 -#define DAC960_StatusBufferSize 16384 -#define DAC960_RebuildProgressSize 200 +#define DAC960_ProgressBufferSize 200 #define DAC960_UserMessageSize 200 +#define DAC960_InitialStatusBufferSize (8192-32) /* - Define the types of DAC960 Controllers that are supported. + Define the DAC960 Controller Firmware Types. */ typedef enum { - DAC960_V5_Controller = 1, /* DAC1164P */ - DAC960_V4_Controller = 2, /* DAC960PTL/PJ/PG */ - DAC960_V3_Controller = 3 /* DAC960PU/PD/PL */ + DAC960_V1_Controller = 1, + DAC960_V2_Controller = 2 } -DAC960_ControllerType_T; +DAC960_FirmwareType_T; + + +/* + Define the DAC960 Controller Hardware Types. +*/ + +typedef enum +{ + DAC960_BA_Controller = 1, /* eXtremeRAID 2000 */ + DAC960_LP_Controller = 2, /* AcceleRAID 352 */ + DAC960_LA_Controller = 3, /* DAC1164P */ + DAC960_PG_Controller = 4, /* DAC960PTL/PJ/PG */ + DAC960_PD_Controller = 5 /* DAC960PU/PD/PL */ +} +DAC960_HardwareType_T; /* @@ -1111,18 +2150,21 @@ static char typedef struct buffer_head BufferHeader_T; typedef struct file File_T; +typedef struct block_device_operations BlockDeviceOperations_T; typedef struct gendisk GenericDiskInfo_T; typedef struct hd_geometry DiskGeometry_T; typedef struct hd_struct DiskPartition_T; typedef struct inode Inode_T; typedef struct inode_operations InodeOperations_T; typedef kdev_t KernelDevice_T; +typedef struct list_head ListHead_T; typedef struct notifier_block NotifierBlock_T; typedef struct pci_dev PCI_Device_T; typedef struct proc_dir_entry PROC_DirectoryEntry_T; typedef unsigned long ProcessorFlags_T; typedef struct pt_regs Registers_T; typedef struct request IO_Request_T; +typedef request_queue_t RequestQueue_T; typedef struct semaphore Semaphore_T; typedef struct super_block SuperBlock_T; typedef struct timer_list Timer_T; @@ -1130,20 +2172,37 @@ typedef wait_queue_head_t WaitQueue_T; /* - Define the DAC960 Controller Status Mailbox structure. + Define the DAC960 V1 Firmware Controller Status Mailbox structure. */ -typedef union DAC960_StatusMailbox +typedef union DAC960_V1_StatusMailbox { - unsigned int Word; /* Bytes 0-3 */ + unsigned int Word; /* Word 0 */ struct { - DAC960_CommandIdentifier_T CommandIdentifier; /* Byte 0 */ + DAC960_V1_CommandIdentifier_T CommandIdentifier; /* Byte 0 */ unsigned char :7; /* Byte 1 Bits 0-6 */ boolean Valid:1; /* Byte 1 Bit 7 */ - DAC960_CommandStatus_T CommandStatus; /* Bytes 2-3 */ + DAC960_V1_CommandStatus_T CommandStatus; /* Bytes 2-3 */ + } Fields; +} +DAC960_V1_StatusMailbox_T; + + +/* + Define the DAC960 V2 Firmware Controller Status Mailbox structure. +*/ + +typedef union DAC960_V2_StatusMailbox +{ + unsigned int Words[2]; /* Words 0-1 */ + struct { + DAC960_V2_CommandIdentifier_T CommandIdentifier; /* Bytes 0-1 */ + DAC960_V2_CommandStatus_T CommandStatus; /* Byte 2 */ + unsigned char RequestSenseLength; /* Byte 3 */ + int DataTransferResidue; /* Bytes 4-7 */ } Fields; } -DAC960_StatusMailbox_T; +DAC960_V2_StatusMailbox_T; /* @@ -1169,9 +2228,8 @@ DAC960_CommandType_T; typedef struct DAC960_Command { + int CommandIdentifier; DAC960_CommandType_T CommandType; - DAC960_CommandMailbox_T CommandMailbox; - DAC960_CommandStatus_T CommandStatus; struct DAC960_Controller *Controller; struct DAC960_Command *Next; Semaphore_T *Semaphore; @@ -1180,9 +2238,31 @@ typedef struct DAC960_Command unsigned int BlockCount; unsigned int SegmentCount; BufferHeader_T *BufferHeader; - DAC960_KernelCommand_T *KernelCommand; - DAC960_ScatterGatherSegment_T - ScatterGatherList[DAC960_MaxScatterGatherSegments]; + void *RequestBuffer; + union { + struct { + DAC960_V1_CommandMailbox_T CommandMailbox; + DAC960_V1_KernelCommand_T *KernelCommand; + DAC960_V1_CommandStatus_T CommandStatus; + DAC960_V1_ScatterGatherSegment_T + ScatterGatherList[DAC960_V1_ScatterGatherLimit] + __attribute__ ((aligned (sizeof(DAC960_V1_ScatterGatherSegment_T)))); + unsigned int EndMarker[0]; + } V1; + struct { + DAC960_V2_CommandMailbox_T CommandMailbox; + DAC960_V2_KernelCommand_T *KernelCommand; + DAC960_V2_CommandStatus_T CommandStatus; + unsigned char RequestSenseLength; + int DataTransferResidue; + DAC960_V2_ScatterGatherSegment_T + ScatterGatherList[DAC960_V2_ScatterGatherLimit] + __attribute__ ((aligned (sizeof(DAC960_V2_ScatterGatherSegment_T)))); + DAC960_SCSI_RequestSense_T RequestSense + __attribute__ ((aligned (sizeof(int)))); + unsigned int EndMarker[0]; + } V2; + } FW; } DAC960_Command_T; @@ -1195,107 +2275,179 @@ typedef struct DAC960_Controller { void *BaseAddress; void *MemoryMappedAddress; - DAC960_ControllerType_T ControllerType; + DAC960_FirmwareType_T FirmwareType; + DAC960_HardwareType_T HardwareType; DAC960_IO_Address_T IO_Address; DAC960_PCI_Address_T PCI_Address; unsigned char ControllerNumber; unsigned char ControllerName[4]; - unsigned char ModelName[12]; - unsigned char FullModelName[18]; - unsigned char FirmwareVersion[14]; + unsigned char ModelName[20]; + unsigned char FullModelName[28]; + unsigned char FirmwareVersion[12]; unsigned char Bus; unsigned char Device; unsigned char Function; unsigned char IRQ_Channel; unsigned char Channels; + unsigned char Targets; unsigned char MemorySize; unsigned char LogicalDriveCount; - unsigned char GeometryTranslationHeads; - unsigned char GeometryTranslationSectors; - unsigned char PendingRebuildFlag; + unsigned short CommandAllocationGroupSize; unsigned short ControllerQueueDepth; unsigned short DriverQueueDepth; unsigned short MaxBlocksPerCommand; - unsigned short MaxScatterGatherSegments; - unsigned short StripeSize; - unsigned short SegmentSize; - unsigned short NewEventLogSequenceNumber; - unsigned short OldEventLogSequenceNumber; - unsigned short InitialStatusLength; - unsigned short CurrentStatusLength; - unsigned short UserStatusLength; - unsigned short RebuildProgressLength; + unsigned short ControllerScatterGatherLimit; + unsigned short DriverScatterGatherLimit; unsigned int ControllerUsageCount; - unsigned int EnquiryIndex; - unsigned int LogicalDriveInformationIndex; - unsigned int ErrorTableIndex; - unsigned int DeviceStateIndex; - unsigned int DeviceStateChannel; - unsigned int DeviceStateTargetID; + unsigned int CombinedStatusBufferLength; + unsigned int InitialStatusLength; + unsigned int CurrentStatusLength; + unsigned int ProgressBufferLength; + unsigned int UserStatusLength; + unsigned long MemoryMailboxPagesAddress; + unsigned long MemoryMailboxPagesOrder; unsigned long MonitoringTimerCount; + unsigned long PrimaryMonitoringTime; unsigned long SecondaryMonitoringTime; unsigned long LastProgressReportTime; unsigned long LastCurrentStatusTime; - boolean DualModeMemoryMailboxInterface; - boolean SAFTE_EnclosureManagementEnabled; + boolean ControllerDetectionSuccessful; boolean ControllerInitialized; boolean MonitoringCommandDeferred; - boolean NeedLogicalDriveInformation; - boolean NeedErrorTableInformation; - boolean NeedDeviceStateInformation; - boolean NeedDeviceInquiryInformation; - boolean NeedDeviceSerialNumberInformation; - boolean NeedRebuildProgress; - boolean NeedConsistencyCheckProgress; boolean EphemeralProgressMessage; - boolean RebuildFlagPending; - boolean RebuildStatusPending; boolean DriveSpinUpMessageDisplayed; + boolean MonitoringAlertMode; Timer_T MonitoringTimer; GenericDiskInfo_T GenericDiskInfo; DAC960_Command_T *FreeCommands; - DAC960_CommandMailbox_T *FirstCommandMailbox; - DAC960_CommandMailbox_T *LastCommandMailbox; - DAC960_CommandMailbox_T *NextCommandMailbox; - DAC960_CommandMailbox_T *PreviousCommandMailbox1; - DAC960_CommandMailbox_T *PreviousCommandMailbox2; - DAC960_StatusMailbox_T *FirstStatusMailbox; - DAC960_StatusMailbox_T *LastStatusMailbox; - DAC960_StatusMailbox_T *NextStatusMailbox; + unsigned char *CombinedStatusBuffer; + unsigned char *CurrentStatusBuffer; + RequestQueue_T *RequestQueue; WaitQueue_T CommandWaitQueue; - DAC960_DCDB_T MonitoringDCDB; - DAC960_Enquiry_T Enquiry[2]; - DAC960_ErrorTable_T ErrorTable[2]; - DAC960_EventLogEntry_T EventLogEntry; - DAC960_RebuildProgress_T RebuildProgress; - DAC960_CommandStatus_T LastRebuildStatus; - DAC960_CommandStatus_T PendingRebuildStatus; - DAC960_LogicalDriveInformation_T - LogicalDriveInformation[2][DAC960_MaxLogicalDrives]; - DAC960_LogicalDriveState_T LogicalDriveInitialState[DAC960_MaxLogicalDrives]; - DAC960_DeviceState_T DeviceState[2][DAC960_MaxChannels][DAC960_MaxTargets]; - DAC960_Command_T Commands[DAC960_MaxDriverQueueDepth]; - DAC960_SCSI_Inquiry_T - InquiryStandardData[DAC960_MaxChannels][DAC960_MaxTargets]; - DAC960_SCSI_Inquiry_UnitSerialNumber_T - InquiryUnitSerialNumber[DAC960_MaxChannels][DAC960_MaxTargets]; + WaitQueue_T HealthStatusWaitQueue; + DAC960_Command_T InitialCommand; + DAC960_Command_T *Commands[DAC960_MaxDriverQueueDepth]; + PROC_DirectoryEntry_T *ControllerProcEntry; + unsigned int LogicalDriveUsageCount[DAC960_MaxLogicalDrives]; + boolean LogicalDriveInitiallyAccessible[DAC960_MaxLogicalDrives]; + void (*QueueCommand)(DAC960_Command_T *Command); + boolean (*ReadControllerConfiguration)(struct DAC960_Controller *); + boolean (*ReadDeviceConfiguration)(struct DAC960_Controller *); + boolean (*ReportDeviceConfiguration)(struct DAC960_Controller *); + void (*QueueReadWriteCommand)(DAC960_Command_T *Command); + union { + struct { + unsigned char GeometryTranslationHeads; + unsigned char GeometryTranslationSectors; + unsigned char PendingRebuildFlag; + unsigned short StripeSize; + unsigned short SegmentSize; + unsigned short NewEventLogSequenceNumber; + unsigned short OldEventLogSequenceNumber; + unsigned short DeviceStateChannel; + unsigned short DeviceStateTargetID; + boolean DualModeMemoryMailboxInterface; + boolean SAFTE_EnclosureManagementEnabled; + boolean NeedLogicalDriveInformation; + boolean NeedErrorTableInformation; + boolean NeedDeviceStateInformation; + boolean NeedDeviceInquiryInformation; + boolean NeedDeviceSerialNumberInformation; + boolean NeedRebuildProgress; + boolean NeedConsistencyCheckProgress; + boolean RebuildProgressFirst; + boolean RebuildFlagPending; + boolean RebuildStatusPending; + DAC960_V1_CommandMailbox_T *FirstCommandMailbox; + DAC960_V1_CommandMailbox_T *LastCommandMailbox; + DAC960_V1_CommandMailbox_T *NextCommandMailbox; + DAC960_V1_CommandMailbox_T *PreviousCommandMailbox1; + DAC960_V1_CommandMailbox_T *PreviousCommandMailbox2; + DAC960_V1_StatusMailbox_T *FirstStatusMailbox; + DAC960_V1_StatusMailbox_T *LastStatusMailbox; + DAC960_V1_StatusMailbox_T *NextStatusMailbox; + DAC960_V1_DCDB_T MonitoringDCDB; + DAC960_V1_Enquiry_T Enquiry; + DAC960_V1_Enquiry_T NewEnquiry; + DAC960_V1_ErrorTable_T ErrorTable; + DAC960_V1_ErrorTable_T NewErrorTable; + DAC960_V1_EventLogEntry_T EventLogEntry; + DAC960_V1_RebuildProgress_T RebuildProgress; + DAC960_V1_CommandStatus_T LastRebuildStatus; + DAC960_V1_CommandStatus_T PendingRebuildStatus; + DAC960_V1_LogicalDriveInformationArray_T LogicalDriveInformation; + DAC960_V1_LogicalDriveInformationArray_T NewLogicalDriveInformation; + DAC960_V1_DeviceState_T + DeviceState[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets]; + DAC960_V1_DeviceState_T NewDeviceState; + DAC960_SCSI_Inquiry_T + InquiryStandardData[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets]; + DAC960_SCSI_Inquiry_UnitSerialNumber_T + InquiryUnitSerialNumber[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets]; + int DeviceResetCount[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets]; + boolean DirectCommandActive[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets]; + } V1; + struct { + unsigned int StatusChangeCounter; + unsigned int NextEventSequenceNumber; + unsigned int PhysicalDeviceIndex; + boolean NeedLogicalDeviceInformation; + boolean NeedPhysicalDeviceInformation; + boolean NeedDeviceSerialNumberInformation; + DAC960_V2_CommandMailbox_T *FirstCommandMailbox; + DAC960_V2_CommandMailbox_T *LastCommandMailbox; + DAC960_V2_CommandMailbox_T *NextCommandMailbox; + DAC960_V2_CommandMailbox_T *PreviousCommandMailbox1; + DAC960_V2_CommandMailbox_T *PreviousCommandMailbox2; + DAC960_V2_StatusMailbox_T *FirstStatusMailbox; + DAC960_V2_StatusMailbox_T *LastStatusMailbox; + DAC960_V2_StatusMailbox_T *NextStatusMailbox; + DAC960_V2_HealthStatusBuffer_T *HealthStatusBuffer; + DAC960_V2_ControllerInfo_T ControllerInformation; + DAC960_V2_ControllerInfo_T NewControllerInformation; + DAC960_V2_LogicalDeviceInfo_T + *LogicalDeviceInformation[DAC960_MaxLogicalDrives]; + DAC960_V2_LogicalDeviceInfo_T NewLogicalDeviceInformation; + DAC960_V2_PhysicalDeviceInfo_T + *PhysicalDeviceInformation[DAC960_V2_MaxPhysicalDevices]; + DAC960_V2_PhysicalDeviceInfo_T NewPhysicalDeviceInformation; + DAC960_SCSI_Inquiry_UnitSerialNumber_T + *InquiryUnitSerialNumber[DAC960_V2_MaxPhysicalDevices]; + DAC960_V2_PhysicalDevice_T + LogicalDriveToVirtualDevice[DAC960_MaxLogicalDrives]; + DAC960_V2_Event_T Event; + } V2; + } FW; DiskPartition_T DiskPartitions[DAC960_MinorCount]; - int LogicalDriveUsageCount[DAC960_MaxLogicalDrives]; int PartitionSizes[DAC960_MinorCount]; int BlockSizes[DAC960_MinorCount]; int MaxSectorsPerRequest[DAC960_MinorCount]; - int MaxSegmentsPerRequest[DAC960_MinorCount]; - int DeviceResetCount[DAC960_MaxChannels][DAC960_MaxTargets]; - boolean DirectCommandActive[DAC960_MaxChannels][DAC960_MaxTargets]; - char InitialStatusBuffer[DAC960_StatusBufferSize]; - char CurrentStatusBuffer[DAC960_StatusBufferSize]; - char UserStatusBuffer[DAC960_UserMessageSize]; - char RebuildProgressBuffer[DAC960_RebuildProgressSize]; + unsigned char ProgressBuffer[DAC960_ProgressBufferSize]; + unsigned char UserStatusBuffer[DAC960_UserMessageSize]; } DAC960_Controller_T; /* + Simplify access to Firmware Version Dependent Data Structure Components + and Functions. +*/ + +#define V1 FW.V1 +#define V2 FW.V2 +#define DAC960_QueueCommand(Command) \ + (Controller->QueueCommand)(Command) +#define DAC960_ReadControllerConfiguration(Controller) \ + (Controller->ReadControllerConfiguration)(Controller) +#define DAC960_ReadDeviceConfiguration(Controller) \ + (Controller->ReadDeviceConfiguration)(Controller) +#define DAC960_ReportDeviceConfiguration(Controller) \ + (Controller->ReportDeviceConfiguration)(Controller) +#define DAC960_QueueReadWriteCommand(Command) \ + (Controller->QueueReadWriteCommand)(Command) + + +/* DAC960_AcquireControllerLock acquires exclusive access to Controller. */ @@ -1370,41 +2522,29 @@ void DAC960_ReleaseControllerLockIH(DAC960_Controller_T *Controller, /* - Define the DAC960 V5 Controller Interface Register Offsets. + Define the DAC960 BA Series Controller Interface Register Offsets. */ -#define DAC960_V5_RegisterWindowSize 0x80 +#define DAC960_BA_RegisterWindowSize 0x80 typedef enum { - DAC960_V5_InboundDoorBellRegisterOffset = 0x60, - DAC960_V5_OutboundDoorBellRegisterOffset = 0x61, - DAC960_V5_InterruptMaskRegisterOffset = 0x34, - DAC960_V5_CommandOpcodeRegisterOffset = 0x50, - DAC960_V5_CommandIdentifierRegisterOffset = 0x51, - DAC960_V5_MailboxRegister2Offset = 0x52, - DAC960_V5_MailboxRegister3Offset = 0x53, - DAC960_V5_MailboxRegister4Offset = 0x54, - DAC960_V5_MailboxRegister5Offset = 0x55, - DAC960_V5_MailboxRegister6Offset = 0x56, - DAC960_V5_MailboxRegister7Offset = 0x57, - DAC960_V5_MailboxRegister8Offset = 0x58, - DAC960_V5_MailboxRegister9Offset = 0x59, - DAC960_V5_MailboxRegister10Offset = 0x5A, - DAC960_V5_MailboxRegister11Offset = 0x5B, - DAC960_V5_MailboxRegister12Offset = 0x5C, - DAC960_V5_StatusCommandIdentifierRegOffset = 0x5D, - DAC960_V5_StatusRegisterOffset = 0x5E, - DAC960_V5_ErrorStatusRegisterOffset = 0x63 + DAC960_BA_InboundDoorBellRegisterOffset = 0x60, + DAC960_BA_OutboundDoorBellRegisterOffset = 0x61, + DAC960_BA_InterruptStatusRegisterOffset = 0x30, + DAC960_BA_InterruptMaskRegisterOffset = 0x34, + DAC960_BA_CommandMailboxBusAddressOffset = 0x50, + DAC960_BA_CommandStatusOffset = 0x58, + DAC960_BA_ErrorStatusRegisterOffset = 0x63 } -DAC960_V5_RegisterOffsets_T; +DAC960_BA_RegisterOffsets_T; /* - Define the structure of the DAC960 V5 Inbound Door Bell Register. + Define the structure of the DAC960 BA Series Inbound Door Bell Register. */ -typedef union DAC960_V5_InboundDoorBellRegister +typedef union DAC960_BA_InboundDoorBellRegister { unsigned char All; struct { @@ -1421,14 +2561,14 @@ typedef union DAC960_V5_InboundDoorBellRegister unsigned char :6; /* Bits 2-7 */ } Read; } -DAC960_V5_InboundDoorBellRegister_T; +DAC960_BA_InboundDoorBellRegister_T; /* - Define the structure of the DAC960 V5 Outbound Door Bell Register. + Define the structure of the DAC960 BA Series Outbound Door Bell Register. */ -typedef union DAC960_V5_OutboundDoorBellRegister +typedef union DAC960_BA_OutboundDoorBellRegister { unsigned char All; struct { @@ -1442,14 +2582,631 @@ typedef union DAC960_V5_OutboundDoorBellRegister unsigned char :6; /* Bits 2-7 */ } Read; } -DAC960_V5_OutboundDoorBellRegister_T; +DAC960_BA_OutboundDoorBellRegister_T; /* - Define the structure of the DAC960 V5 Interrupt Mask Register. + Define the structure of the DAC960 BA Series Interrupt Mask Register. */ -typedef union DAC960_V5_InterruptMaskRegister +typedef union DAC960_BA_InterruptMaskRegister +{ + unsigned char All; + struct { + unsigned int :2; /* Bits 0-1 */ + boolean DisableInterrupts:1; /* Bit 2 */ + boolean DisableInterruptsI2O:1; /* Bit 3 */ + unsigned int :4; /* Bits 4-7 */ + } Bits; +} +DAC960_BA_InterruptMaskRegister_T; + + +/* + Define the structure of the DAC960 BA Series Error Status Register. +*/ + +typedef union DAC960_BA_ErrorStatusRegister +{ + unsigned char All; + struct { + unsigned int :2; /* Bits 0-1 */ + boolean ErrorStatusPending:1; /* Bit 2 */ + unsigned int :5; /* Bits 3-7 */ + } Bits; +} +DAC960_BA_ErrorStatusRegister_T; + + +/* + Define inline functions to provide an abstraction for reading and writing the + DAC960 BA Series Controller Interface Registers. +*/ + +static inline +void DAC960_BA_HardwareMailboxNewCommand(void *ControllerBaseAddress) +{ + DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = 0; + InboundDoorBellRegister.Write.HardwareMailboxNewCommand = true; + writeb(InboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_BA_InboundDoorBellRegisterOffset); +} + +static inline +void DAC960_BA_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress) +{ + DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = 0; + InboundDoorBellRegister.Write.AcknowledgeHardwareMailboxStatus = true; + writeb(InboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_BA_InboundDoorBellRegisterOffset); +} + +static inline +void DAC960_BA_GenerateInterrupt(void *ControllerBaseAddress) +{ + DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = 0; + InboundDoorBellRegister.Write.GenerateInterrupt = true; + writeb(InboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_BA_InboundDoorBellRegisterOffset); +} + +static inline +void DAC960_BA_ControllerReset(void *ControllerBaseAddress) +{ + DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = 0; + InboundDoorBellRegister.Write.ControllerReset = true; + writeb(InboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_BA_InboundDoorBellRegisterOffset); +} + +static inline +void DAC960_BA_MemoryMailboxNewCommand(void *ControllerBaseAddress) +{ + DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = 0; + InboundDoorBellRegister.Write.MemoryMailboxNewCommand = true; + writeb(InboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_BA_InboundDoorBellRegisterOffset); +} + +static inline +boolean DAC960_BA_HardwareMailboxFullP(void *ControllerBaseAddress) +{ + DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = + readb(ControllerBaseAddress + DAC960_BA_InboundDoorBellRegisterOffset); + return !InboundDoorBellRegister.Read.HardwareMailboxEmpty; +} + +static inline +boolean DAC960_BA_InitializationInProgressP(void *ControllerBaseAddress) +{ + DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = + readb(ControllerBaseAddress + DAC960_BA_InboundDoorBellRegisterOffset); + return !InboundDoorBellRegister.Read.InitializationNotInProgress; +} + +static inline +void DAC960_BA_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress) +{ + DAC960_BA_OutboundDoorBellRegister_T OutboundDoorBellRegister; + OutboundDoorBellRegister.All = 0; + OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true; + writeb(OutboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_BA_OutboundDoorBellRegisterOffset); +} + +static inline +void DAC960_BA_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress) +{ + DAC960_BA_OutboundDoorBellRegister_T OutboundDoorBellRegister; + OutboundDoorBellRegister.All = 0; + OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true; + writeb(OutboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_BA_OutboundDoorBellRegisterOffset); +} + +static inline +void DAC960_BA_AcknowledgeInterrupt(void *ControllerBaseAddress) +{ + DAC960_BA_OutboundDoorBellRegister_T OutboundDoorBellRegister; + OutboundDoorBellRegister.All = 0; + OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true; + OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true; + writeb(OutboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_BA_OutboundDoorBellRegisterOffset); +} + +static inline +boolean DAC960_BA_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress) +{ + DAC960_BA_OutboundDoorBellRegister_T OutboundDoorBellRegister; + OutboundDoorBellRegister.All = + readb(ControllerBaseAddress + DAC960_BA_OutboundDoorBellRegisterOffset); + return OutboundDoorBellRegister.Read.HardwareMailboxStatusAvailable; +} + +static inline +boolean DAC960_BA_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress) +{ + DAC960_BA_OutboundDoorBellRegister_T OutboundDoorBellRegister; + OutboundDoorBellRegister.All = + readb(ControllerBaseAddress + DAC960_BA_OutboundDoorBellRegisterOffset); + return OutboundDoorBellRegister.Read.MemoryMailboxStatusAvailable; +} + +static inline +void DAC960_BA_EnableInterrupts(void *ControllerBaseAddress) +{ + DAC960_BA_InterruptMaskRegister_T InterruptMaskRegister; + InterruptMaskRegister.All = 0xFF; + InterruptMaskRegister.Bits.DisableInterrupts = false; + InterruptMaskRegister.Bits.DisableInterruptsI2O = true; + writeb(InterruptMaskRegister.All, + ControllerBaseAddress + DAC960_BA_InterruptMaskRegisterOffset); +} + +static inline +void DAC960_BA_DisableInterrupts(void *ControllerBaseAddress) +{ + DAC960_BA_InterruptMaskRegister_T InterruptMaskRegister; + InterruptMaskRegister.All = 0xFF; + InterruptMaskRegister.Bits.DisableInterrupts = true; + InterruptMaskRegister.Bits.DisableInterruptsI2O = true; + writeb(InterruptMaskRegister.All, + ControllerBaseAddress + DAC960_BA_InterruptMaskRegisterOffset); +} + +static inline +boolean DAC960_BA_InterruptsEnabledP(void *ControllerBaseAddress) +{ + DAC960_BA_InterruptMaskRegister_T InterruptMaskRegister; + InterruptMaskRegister.All = + readb(ControllerBaseAddress + DAC960_BA_InterruptMaskRegisterOffset); + return !InterruptMaskRegister.Bits.DisableInterrupts; +} + +static inline +void DAC960_BA_WriteCommandMailbox(DAC960_V2_CommandMailbox_T + *MemoryCommandMailbox, + DAC960_V2_CommandMailbox_T + *CommandMailbox) +{ + memcpy(&MemoryCommandMailbox->Words[1], &CommandMailbox->Words[1], + sizeof(DAC960_V2_CommandMailbox_T) - sizeof(unsigned int)); + wmb(); + MemoryCommandMailbox->Words[0] = CommandMailbox->Words[0]; + mb(); +} + +static inline +void DAC960_BA_WriteHardwareMailbox(void *ControllerBaseAddress, + DAC960_V2_CommandMailbox_T *CommandMailbox) +{ + writel(Virtual_to_Bus(CommandMailbox), + ControllerBaseAddress + DAC960_BA_CommandMailboxBusAddressOffset); +} + +static inline DAC960_V2_CommandIdentifier_T +DAC960_BA_ReadCommandIdentifier(void *ControllerBaseAddress) +{ + return readw(ControllerBaseAddress + DAC960_BA_CommandStatusOffset); +} + +static inline DAC960_V2_CommandStatus_T +DAC960_BA_ReadCommandStatus(void *ControllerBaseAddress) +{ + return readw(ControllerBaseAddress + DAC960_BA_CommandStatusOffset + 2); +} + +static inline boolean +DAC960_BA_ReadErrorStatus(void *ControllerBaseAddress, + unsigned char *ErrorStatus, + unsigned char *Parameter0, + unsigned char *Parameter1) +{ + DAC960_BA_ErrorStatusRegister_T ErrorStatusRegister; + ErrorStatusRegister.All = + readb(ControllerBaseAddress + DAC960_BA_ErrorStatusRegisterOffset); + if (!ErrorStatusRegister.Bits.ErrorStatusPending) return false; + ErrorStatusRegister.Bits.ErrorStatusPending = false; + *ErrorStatus = ErrorStatusRegister.All; + *Parameter0 = + readb(ControllerBaseAddress + DAC960_BA_CommandMailboxBusAddressOffset + 0); + *Parameter1 = + readb(ControllerBaseAddress + DAC960_BA_CommandMailboxBusAddressOffset + 1); + writeb(0xFF, ControllerBaseAddress + DAC960_BA_ErrorStatusRegisterOffset); + return true; +} + + +/* + Define the DAC960 LP Series Controller Interface Register Offsets. +*/ + +#define DAC960_LP_RegisterWindowSize 0x80 + +typedef enum +{ + DAC960_LP_InboundDoorBellRegisterOffset = 0x20, + DAC960_LP_OutboundDoorBellRegisterOffset = 0x2C, + DAC960_LP_InterruptStatusRegisterOffset = 0x30, + DAC960_LP_InterruptMaskRegisterOffset = 0x34, + DAC960_LP_CommandMailboxBusAddressOffset = 0x10, + DAC960_LP_CommandStatusOffset = 0x18, + DAC960_LP_ErrorStatusRegisterOffset = 0x2E +} +DAC960_LP_RegisterOffsets_T; + + +/* + Define the structure of the DAC960 LP Series Inbound Door Bell Register. +*/ + +typedef union DAC960_LP_InboundDoorBellRegister +{ + unsigned char All; + struct { + boolean HardwareMailboxNewCommand:1; /* Bit 0 */ + boolean AcknowledgeHardwareMailboxStatus:1; /* Bit 1 */ + boolean GenerateInterrupt:1; /* Bit 2 */ + boolean ControllerReset:1; /* Bit 3 */ + boolean MemoryMailboxNewCommand:1; /* Bit 4 */ + unsigned char :3; /* Bits 5-7 */ + } Write; + struct { + boolean HardwareMailboxFull:1; /* Bit 0 */ + boolean InitializationInProgress:1; /* Bit 1 */ + unsigned char :6; /* Bits 2-7 */ + } Read; +} +DAC960_LP_InboundDoorBellRegister_T; + + +/* + Define the structure of the DAC960 LP Series Outbound Door Bell Register. +*/ + +typedef union DAC960_LP_OutboundDoorBellRegister +{ + unsigned char All; + struct { + boolean AcknowledgeHardwareMailboxInterrupt:1; /* Bit 0 */ + boolean AcknowledgeMemoryMailboxInterrupt:1; /* Bit 1 */ + unsigned char :6; /* Bits 2-7 */ + } Write; + struct { + boolean HardwareMailboxStatusAvailable:1; /* Bit 0 */ + boolean MemoryMailboxStatusAvailable:1; /* Bit 1 */ + unsigned char :6; /* Bits 2-7 */ + } Read; +} +DAC960_LP_OutboundDoorBellRegister_T; + + +/* + Define the structure of the DAC960 LP Series Interrupt Mask Register. +*/ + +typedef union DAC960_LP_InterruptMaskRegister +{ + unsigned char All; + struct { + unsigned int :2; /* Bits 0-1 */ + boolean DisableInterrupts:1; /* Bit 2 */ + unsigned int :5; /* Bits 3-7 */ + } Bits; +} +DAC960_LP_InterruptMaskRegister_T; + + +/* + Define the structure of the DAC960 LP Series Error Status Register. +*/ + +typedef union DAC960_LP_ErrorStatusRegister +{ + unsigned char All; + struct { + unsigned int :2; /* Bits 0-1 */ + boolean ErrorStatusPending:1; /* Bit 2 */ + unsigned int :5; /* Bits 3-7 */ + } Bits; +} +DAC960_LP_ErrorStatusRegister_T; + + +/* + Define inline functions to provide an abstraction for reading and writing the + DAC960 LP Series Controller Interface Registers. +*/ + +static inline +void DAC960_LP_HardwareMailboxNewCommand(void *ControllerBaseAddress) +{ + DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = 0; + InboundDoorBellRegister.Write.HardwareMailboxNewCommand = true; + writeb(InboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_LP_InboundDoorBellRegisterOffset); +} + +static inline +void DAC960_LP_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress) +{ + DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = 0; + InboundDoorBellRegister.Write.AcknowledgeHardwareMailboxStatus = true; + writeb(InboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_LP_InboundDoorBellRegisterOffset); +} + +static inline +void DAC960_LP_GenerateInterrupt(void *ControllerBaseAddress) +{ + DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = 0; + InboundDoorBellRegister.Write.GenerateInterrupt = true; + writeb(InboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_LP_InboundDoorBellRegisterOffset); +} + +static inline +void DAC960_LP_ControllerReset(void *ControllerBaseAddress) +{ + DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = 0; + InboundDoorBellRegister.Write.ControllerReset = true; + writeb(InboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_LP_InboundDoorBellRegisterOffset); +} + +static inline +void DAC960_LP_MemoryMailboxNewCommand(void *ControllerBaseAddress) +{ + DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = 0; + InboundDoorBellRegister.Write.MemoryMailboxNewCommand = true; + writeb(InboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_LP_InboundDoorBellRegisterOffset); +} + +static inline +boolean DAC960_LP_HardwareMailboxFullP(void *ControllerBaseAddress) +{ + DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = + readb(ControllerBaseAddress + DAC960_LP_InboundDoorBellRegisterOffset); + return InboundDoorBellRegister.Read.HardwareMailboxFull; +} + +static inline +boolean DAC960_LP_InitializationInProgressP(void *ControllerBaseAddress) +{ + DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = + readb(ControllerBaseAddress + DAC960_LP_InboundDoorBellRegisterOffset); + return InboundDoorBellRegister.Read.InitializationInProgress; +} + +static inline +void DAC960_LP_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress) +{ + DAC960_LP_OutboundDoorBellRegister_T OutboundDoorBellRegister; + OutboundDoorBellRegister.All = 0; + OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true; + writeb(OutboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_LP_OutboundDoorBellRegisterOffset); +} + +static inline +void DAC960_LP_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress) +{ + DAC960_LP_OutboundDoorBellRegister_T OutboundDoorBellRegister; + OutboundDoorBellRegister.All = 0; + OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true; + writeb(OutboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_LP_OutboundDoorBellRegisterOffset); +} + +static inline +void DAC960_LP_AcknowledgeInterrupt(void *ControllerBaseAddress) +{ + DAC960_LP_OutboundDoorBellRegister_T OutboundDoorBellRegister; + OutboundDoorBellRegister.All = 0; + OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true; + OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true; + writeb(OutboundDoorBellRegister.All, + ControllerBaseAddress + DAC960_LP_OutboundDoorBellRegisterOffset); +} + +static inline +boolean DAC960_LP_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress) +{ + DAC960_LP_OutboundDoorBellRegister_T OutboundDoorBellRegister; + OutboundDoorBellRegister.All = + readb(ControllerBaseAddress + DAC960_LP_OutboundDoorBellRegisterOffset); + return OutboundDoorBellRegister.Read.HardwareMailboxStatusAvailable; +} + +static inline +boolean DAC960_LP_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress) +{ + DAC960_LP_OutboundDoorBellRegister_T OutboundDoorBellRegister; + OutboundDoorBellRegister.All = + readb(ControllerBaseAddress + DAC960_LP_OutboundDoorBellRegisterOffset); + return OutboundDoorBellRegister.Read.MemoryMailboxStatusAvailable; +} + +static inline +void DAC960_LP_EnableInterrupts(void *ControllerBaseAddress) +{ + DAC960_LP_InterruptMaskRegister_T InterruptMaskRegister; + InterruptMaskRegister.All = 0xFF; + InterruptMaskRegister.Bits.DisableInterrupts = false; + writeb(InterruptMaskRegister.All, + ControllerBaseAddress + DAC960_LP_InterruptMaskRegisterOffset); +} + +static inline +void DAC960_LP_DisableInterrupts(void *ControllerBaseAddress) +{ + DAC960_LP_InterruptMaskRegister_T InterruptMaskRegister; + InterruptMaskRegister.All = 0xFF; + InterruptMaskRegister.Bits.DisableInterrupts = true; + writeb(InterruptMaskRegister.All, + ControllerBaseAddress + DAC960_LP_InterruptMaskRegisterOffset); +} + +static inline +boolean DAC960_LP_InterruptsEnabledP(void *ControllerBaseAddress) +{ + DAC960_LP_InterruptMaskRegister_T InterruptMaskRegister; + InterruptMaskRegister.All = + readb(ControllerBaseAddress + DAC960_LP_InterruptMaskRegisterOffset); + return !InterruptMaskRegister.Bits.DisableInterrupts; +} + +static inline +void DAC960_LP_WriteCommandMailbox(DAC960_V2_CommandMailbox_T + *MemoryCommandMailbox, + DAC960_V2_CommandMailbox_T + *CommandMailbox) +{ + memcpy(&MemoryCommandMailbox->Words[1], &CommandMailbox->Words[1], + sizeof(DAC960_V2_CommandMailbox_T) - sizeof(unsigned int)); + wmb(); + MemoryCommandMailbox->Words[0] = CommandMailbox->Words[0]; + mb(); +} + +static inline +void DAC960_LP_WriteHardwareMailbox(void *ControllerBaseAddress, + DAC960_V2_CommandMailbox_T *CommandMailbox) +{ + writel(Virtual_to_Bus(CommandMailbox), + ControllerBaseAddress + DAC960_LP_CommandMailboxBusAddressOffset); +} + +static inline DAC960_V2_CommandIdentifier_T +DAC960_LP_ReadCommandIdentifier(void *ControllerBaseAddress) +{ + return readw(ControllerBaseAddress + DAC960_LP_CommandStatusOffset); +} + +static inline DAC960_V2_CommandStatus_T +DAC960_LP_ReadCommandStatus(void *ControllerBaseAddress) +{ + return readw(ControllerBaseAddress + DAC960_LP_CommandStatusOffset + 2); +} + +static inline boolean +DAC960_LP_ReadErrorStatus(void *ControllerBaseAddress, + unsigned char *ErrorStatus, + unsigned char *Parameter0, + unsigned char *Parameter1) +{ + DAC960_LP_ErrorStatusRegister_T ErrorStatusRegister; + ErrorStatusRegister.All = + readb(ControllerBaseAddress + DAC960_LP_ErrorStatusRegisterOffset); + if (!ErrorStatusRegister.Bits.ErrorStatusPending) return false; + ErrorStatusRegister.Bits.ErrorStatusPending = false; + *ErrorStatus = ErrorStatusRegister.All; + *Parameter0 = + readb(ControllerBaseAddress + DAC960_LP_CommandMailboxBusAddressOffset + 0); + *Parameter1 = + readb(ControllerBaseAddress + DAC960_LP_CommandMailboxBusAddressOffset + 1); + writeb(0xFF, ControllerBaseAddress + DAC960_LP_ErrorStatusRegisterOffset); + return true; +} + + +/* + Define the DAC960 LA Series Controller Interface Register Offsets. +*/ + +#define DAC960_LA_RegisterWindowSize 0x80 + +typedef enum +{ + DAC960_LA_InboundDoorBellRegisterOffset = 0x60, + DAC960_LA_OutboundDoorBellRegisterOffset = 0x61, + DAC960_LA_InterruptMaskRegisterOffset = 0x34, + DAC960_LA_CommandOpcodeRegisterOffset = 0x50, + DAC960_LA_CommandIdentifierRegisterOffset = 0x51, + DAC960_LA_MailboxRegister2Offset = 0x52, + DAC960_LA_MailboxRegister3Offset = 0x53, + DAC960_LA_MailboxRegister4Offset = 0x54, + DAC960_LA_MailboxRegister5Offset = 0x55, + DAC960_LA_MailboxRegister6Offset = 0x56, + DAC960_LA_MailboxRegister7Offset = 0x57, + DAC960_LA_MailboxRegister8Offset = 0x58, + DAC960_LA_MailboxRegister9Offset = 0x59, + DAC960_LA_MailboxRegister10Offset = 0x5A, + DAC960_LA_MailboxRegister11Offset = 0x5B, + DAC960_LA_MailboxRegister12Offset = 0x5C, + DAC960_LA_StatusCommandIdentifierRegOffset = 0x5D, + DAC960_LA_StatusRegisterOffset = 0x5E, + DAC960_LA_ErrorStatusRegisterOffset = 0x63 +} +DAC960_LA_RegisterOffsets_T; + + +/* + Define the structure of the DAC960 LA Series Inbound Door Bell Register. +*/ + +typedef union DAC960_LA_InboundDoorBellRegister +{ + unsigned char All; + struct { + boolean HardwareMailboxNewCommand:1; /* Bit 0 */ + boolean AcknowledgeHardwareMailboxStatus:1; /* Bit 1 */ + boolean GenerateInterrupt:1; /* Bit 2 */ + boolean ControllerReset:1; /* Bit 3 */ + boolean MemoryMailboxNewCommand:1; /* Bit 4 */ + unsigned char :3; /* Bits 5-7 */ + } Write; + struct { + boolean HardwareMailboxEmpty:1; /* Bit 0 */ + boolean InitializationNotInProgress:1; /* Bit 1 */ + unsigned char :6; /* Bits 2-7 */ + } Read; +} +DAC960_LA_InboundDoorBellRegister_T; + + +/* + Define the structure of the DAC960 LA Series Outbound Door Bell Register. +*/ + +typedef union DAC960_LA_OutboundDoorBellRegister +{ + unsigned char All; + struct { + boolean AcknowledgeHardwareMailboxInterrupt:1; /* Bit 0 */ + boolean AcknowledgeMemoryMailboxInterrupt:1; /* Bit 1 */ + unsigned char :6; /* Bits 2-7 */ + } Write; + struct { + boolean HardwareMailboxStatusAvailable:1; /* Bit 0 */ + boolean MemoryMailboxStatusAvailable:1; /* Bit 1 */ + unsigned char :6; /* Bits 2-7 */ + } Read; +} +DAC960_LA_OutboundDoorBellRegister_T; + + +/* + Define the structure of the DAC960 LA Series Interrupt Mask Register. +*/ + +typedef union DAC960_LA_InterruptMaskRegister { unsigned char All; struct { @@ -1458,14 +3215,14 @@ typedef union DAC960_V5_InterruptMaskRegister unsigned char :5; /* Bits 3-7 */ } Bits; } -DAC960_V5_InterruptMaskRegister_T; +DAC960_LA_InterruptMaskRegister_T; /* - Define the structure of the DAC960 V5 Error Status Register. + Define the structure of the DAC960 LA Series Error Status Register. */ -typedef union DAC960_V5_ErrorStatusRegister +typedef union DAC960_LA_ErrorStatusRegister { unsigned char All; struct { @@ -1474,288 +3231,294 @@ typedef union DAC960_V5_ErrorStatusRegister unsigned int :5; /* Bits 3-7 */ } Bits; } -DAC960_V5_ErrorStatusRegister_T; +DAC960_LA_ErrorStatusRegister_T; /* Define inline functions to provide an abstraction for reading and writing the - DAC960 V5 Controller Interface Registers. + DAC960 LA Series Controller Interface Registers. */ static inline -void DAC960_V5_HardwareMailboxNewCommand(void *ControllerBaseAddress) +void DAC960_LA_HardwareMailboxNewCommand(void *ControllerBaseAddress) { - DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; InboundDoorBellRegister.Write.HardwareMailboxNewCommand = true; writeb(InboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_LA_InboundDoorBellRegisterOffset); } static inline -void DAC960_V5_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress) +void DAC960_LA_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress) { - DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; InboundDoorBellRegister.Write.AcknowledgeHardwareMailboxStatus = true; writeb(InboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_LA_InboundDoorBellRegisterOffset); } static inline -void DAC960_V5_GenerateInterrupt(void *ControllerBaseAddress) +void DAC960_LA_GenerateInterrupt(void *ControllerBaseAddress) { - DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; InboundDoorBellRegister.Write.GenerateInterrupt = true; writeb(InboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_LA_InboundDoorBellRegisterOffset); } static inline -void DAC960_V5_ControllerReset(void *ControllerBaseAddress) +void DAC960_LA_ControllerReset(void *ControllerBaseAddress) { - DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; InboundDoorBellRegister.Write.ControllerReset = true; writeb(InboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_LA_InboundDoorBellRegisterOffset); } static inline -void DAC960_V5_MemoryMailboxNewCommand(void *ControllerBaseAddress) +void DAC960_LA_MemoryMailboxNewCommand(void *ControllerBaseAddress) { - DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; InboundDoorBellRegister.Write.MemoryMailboxNewCommand = true; writeb(InboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_LA_InboundDoorBellRegisterOffset); } static inline -boolean DAC960_V5_HardwareMailboxFullP(void *ControllerBaseAddress) +boolean DAC960_LA_HardwareMailboxFullP(void *ControllerBaseAddress) { - DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = - readb(ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset); + readb(ControllerBaseAddress + DAC960_LA_InboundDoorBellRegisterOffset); return !InboundDoorBellRegister.Read.HardwareMailboxEmpty; } static inline -boolean DAC960_V5_InitializationInProgressP(void *ControllerBaseAddress) +boolean DAC960_LA_InitializationInProgressP(void *ControllerBaseAddress) { - DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = - readb(ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset); + readb(ControllerBaseAddress + DAC960_LA_InboundDoorBellRegisterOffset); return !InboundDoorBellRegister.Read.InitializationNotInProgress; } static inline -void DAC960_V5_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress) +void DAC960_LA_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress) { - DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister; + DAC960_LA_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = 0; OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true; writeb(OutboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V5_OutboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_LA_OutboundDoorBellRegisterOffset); } static inline -void DAC960_V5_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress) +void DAC960_LA_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress) { - DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister; + DAC960_LA_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = 0; OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true; writeb(OutboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V5_OutboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_LA_OutboundDoorBellRegisterOffset); } static inline -void DAC960_V5_AcknowledgeInterrupt(void *ControllerBaseAddress) +void DAC960_LA_AcknowledgeInterrupt(void *ControllerBaseAddress) { - DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister; + DAC960_LA_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = 0; OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true; OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true; writeb(OutboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V5_OutboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_LA_OutboundDoorBellRegisterOffset); } static inline -boolean DAC960_V5_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress) +boolean DAC960_LA_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress) { - DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister; + DAC960_LA_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = - readb(ControllerBaseAddress + DAC960_V5_OutboundDoorBellRegisterOffset); + readb(ControllerBaseAddress + DAC960_LA_OutboundDoorBellRegisterOffset); return OutboundDoorBellRegister.Read.HardwareMailboxStatusAvailable; } static inline -boolean DAC960_V5_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress) +boolean DAC960_LA_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress) { - DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister; + DAC960_LA_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = - readb(ControllerBaseAddress + DAC960_V5_OutboundDoorBellRegisterOffset); + readb(ControllerBaseAddress + DAC960_LA_OutboundDoorBellRegisterOffset); return OutboundDoorBellRegister.Read.MemoryMailboxStatusAvailable; } static inline -void DAC960_V5_EnableInterrupts(void *ControllerBaseAddress) +void DAC960_LA_EnableInterrupts(void *ControllerBaseAddress) { - DAC960_V5_InterruptMaskRegister_T InterruptMaskRegister; + DAC960_LA_InterruptMaskRegister_T InterruptMaskRegister; InterruptMaskRegister.All = 0xFF; InterruptMaskRegister.Bits.DisableInterrupts = false; writeb(InterruptMaskRegister.All, - ControllerBaseAddress + DAC960_V5_InterruptMaskRegisterOffset); + ControllerBaseAddress + DAC960_LA_InterruptMaskRegisterOffset); } static inline -void DAC960_V5_DisableInterrupts(void *ControllerBaseAddress) +void DAC960_LA_DisableInterrupts(void *ControllerBaseAddress) { - DAC960_V5_InterruptMaskRegister_T InterruptMaskRegister; + DAC960_LA_InterruptMaskRegister_T InterruptMaskRegister; InterruptMaskRegister.All = 0xFF; InterruptMaskRegister.Bits.DisableInterrupts = true; writeb(InterruptMaskRegister.All, - ControllerBaseAddress + DAC960_V5_InterruptMaskRegisterOffset); + ControllerBaseAddress + DAC960_LA_InterruptMaskRegisterOffset); } static inline -boolean DAC960_V5_InterruptsEnabledP(void *ControllerBaseAddress) +boolean DAC960_LA_InterruptsEnabledP(void *ControllerBaseAddress) { - DAC960_V5_InterruptMaskRegister_T InterruptMaskRegister; + DAC960_LA_InterruptMaskRegister_T InterruptMaskRegister; InterruptMaskRegister.All = - readb(ControllerBaseAddress + DAC960_V5_InterruptMaskRegisterOffset); + readb(ControllerBaseAddress + DAC960_LA_InterruptMaskRegisterOffset); return !InterruptMaskRegister.Bits.DisableInterrupts; } static inline -void DAC960_V5_WriteCommandMailbox(DAC960_CommandMailbox_T *NextCommandMailbox, - DAC960_CommandMailbox_T *CommandMailbox) +void DAC960_LA_WriteCommandMailbox(DAC960_V1_CommandMailbox_T + *MemoryCommandMailbox, + DAC960_V1_CommandMailbox_T + *CommandMailbox) { - NextCommandMailbox->Words[1] = CommandMailbox->Words[1]; - NextCommandMailbox->Words[2] = CommandMailbox->Words[2]; - NextCommandMailbox->Words[3] = CommandMailbox->Words[3]; + MemoryCommandMailbox->Words[1] = CommandMailbox->Words[1]; + MemoryCommandMailbox->Words[2] = CommandMailbox->Words[2]; + MemoryCommandMailbox->Words[3] = CommandMailbox->Words[3]; wmb(); - NextCommandMailbox->Words[0] = CommandMailbox->Words[0]; + MemoryCommandMailbox->Words[0] = CommandMailbox->Words[0]; mb(); } static inline -void DAC960_V5_WriteHardwareMailbox(void *ControllerBaseAddress, - DAC960_CommandMailbox_T *CommandMailbox) +void DAC960_LA_WriteHardwareMailbox(void *ControllerBaseAddress, + DAC960_V1_CommandMailbox_T *CommandMailbox) { writel(CommandMailbox->Words[0], - ControllerBaseAddress + DAC960_V5_CommandOpcodeRegisterOffset); + ControllerBaseAddress + DAC960_LA_CommandOpcodeRegisterOffset); writel(CommandMailbox->Words[1], - ControllerBaseAddress + DAC960_V5_MailboxRegister4Offset); + ControllerBaseAddress + DAC960_LA_MailboxRegister4Offset); writel(CommandMailbox->Words[2], - ControllerBaseAddress + DAC960_V5_MailboxRegister8Offset); + ControllerBaseAddress + DAC960_LA_MailboxRegister8Offset); writeb(CommandMailbox->Bytes[12], - ControllerBaseAddress + DAC960_V5_MailboxRegister12Offset); + ControllerBaseAddress + DAC960_LA_MailboxRegister12Offset); } -static inline DAC960_CommandIdentifier_T -DAC960_V5_ReadStatusCommandIdentifier(void *ControllerBaseAddress) +static inline DAC960_V1_CommandIdentifier_T +DAC960_LA_ReadStatusCommandIdentifier(void *ControllerBaseAddress) { return readb(ControllerBaseAddress - + DAC960_V5_StatusCommandIdentifierRegOffset); + + DAC960_LA_StatusCommandIdentifierRegOffset); } -static inline DAC960_CommandStatus_T -DAC960_V5_ReadStatusRegister(void *ControllerBaseAddress) +static inline DAC960_V1_CommandStatus_T +DAC960_LA_ReadStatusRegister(void *ControllerBaseAddress) { - return readw(ControllerBaseAddress + DAC960_V5_StatusRegisterOffset); + return readw(ControllerBaseAddress + DAC960_LA_StatusRegisterOffset); } static inline boolean -DAC960_V5_ReadErrorStatus(void *ControllerBaseAddress, +DAC960_LA_ReadErrorStatus(void *ControllerBaseAddress, unsigned char *ErrorStatus, unsigned char *Parameter0, unsigned char *Parameter1) { - DAC960_V5_ErrorStatusRegister_T ErrorStatusRegister; + DAC960_LA_ErrorStatusRegister_T ErrorStatusRegister; ErrorStatusRegister.All = - readb(ControllerBaseAddress + DAC960_V5_ErrorStatusRegisterOffset); + readb(ControllerBaseAddress + DAC960_LA_ErrorStatusRegisterOffset); if (!ErrorStatusRegister.Bits.ErrorStatusPending) return false; ErrorStatusRegister.Bits.ErrorStatusPending = false; *ErrorStatus = ErrorStatusRegister.All; *Parameter0 = - readb(ControllerBaseAddress + DAC960_V5_CommandOpcodeRegisterOffset); + readb(ControllerBaseAddress + DAC960_LA_CommandOpcodeRegisterOffset); *Parameter1 = - readb(ControllerBaseAddress + DAC960_V5_CommandIdentifierRegisterOffset); - writeb(0xFF, ControllerBaseAddress + DAC960_V5_ErrorStatusRegisterOffset); + readb(ControllerBaseAddress + DAC960_LA_CommandIdentifierRegisterOffset); + writeb(0xFF, ControllerBaseAddress + DAC960_LA_ErrorStatusRegisterOffset); return true; } static inline -void DAC960_V5_SaveMemoryMailboxInfo(DAC960_Controller_T *Controller) +void DAC960_LA_SaveMemoryMailboxInfo(DAC960_Controller_T *Controller) { +#ifdef __i386__ void *ControllerBaseAddress = Controller->BaseAddress; writel(0x743C485E, - ControllerBaseAddress + DAC960_V5_CommandOpcodeRegisterOffset); - writel((unsigned long) Controller->FirstCommandMailbox, - ControllerBaseAddress + DAC960_V5_MailboxRegister4Offset); - writew(Controller->NextCommandMailbox - Controller->FirstCommandMailbox, - ControllerBaseAddress + DAC960_V5_MailboxRegister8Offset); - writew(Controller->NextStatusMailbox - Controller->FirstStatusMailbox, - ControllerBaseAddress + DAC960_V5_MailboxRegister10Offset); + ControllerBaseAddress + DAC960_LA_CommandOpcodeRegisterOffset); + writel((unsigned long) Controller->V1.FirstCommandMailbox, + ControllerBaseAddress + DAC960_LA_MailboxRegister4Offset); + writew(Controller->V1.NextCommandMailbox - Controller->V1.FirstCommandMailbox, + ControllerBaseAddress + DAC960_LA_MailboxRegister8Offset); + writew(Controller->V1.NextStatusMailbox - Controller->V1.FirstStatusMailbox, + ControllerBaseAddress + DAC960_LA_MailboxRegister10Offset); +#endif } static inline -void DAC960_V5_RestoreMemoryMailboxInfo(DAC960_Controller_T *Controller, +void DAC960_LA_RestoreMemoryMailboxInfo(DAC960_Controller_T *Controller, void **MemoryMailboxAddress, short *NextCommandMailboxIndex, short *NextStatusMailboxIndex) { +#ifdef __i386__ void *ControllerBaseAddress = Controller->BaseAddress; if (readl(ControllerBaseAddress - + DAC960_V5_CommandOpcodeRegisterOffset) != 0x743C485E) + + DAC960_LA_CommandOpcodeRegisterOffset) != 0x743C485E) return; *MemoryMailboxAddress = - (void *) readl(ControllerBaseAddress + DAC960_V5_MailboxRegister4Offset); + (void *) readl(ControllerBaseAddress + DAC960_LA_MailboxRegister4Offset); *NextCommandMailboxIndex = - readw(ControllerBaseAddress + DAC960_V5_MailboxRegister8Offset); + readw(ControllerBaseAddress + DAC960_LA_MailboxRegister8Offset); *NextStatusMailboxIndex = - readw(ControllerBaseAddress + DAC960_V5_MailboxRegister10Offset); + readw(ControllerBaseAddress + DAC960_LA_MailboxRegister10Offset); +#endif } /* - Define the DAC960 V4 Controller Interface Register Offsets. + Define the DAC960 PG Series Controller Interface Register Offsets. */ -#define DAC960_V4_RegisterWindowSize 0x2000 +#define DAC960_PG_RegisterWindowSize 0x2000 typedef enum { - DAC960_V4_InboundDoorBellRegisterOffset = 0x0020, - DAC960_V4_OutboundDoorBellRegisterOffset = 0x002C, - DAC960_V4_InterruptMaskRegisterOffset = 0x0034, - DAC960_V4_CommandOpcodeRegisterOffset = 0x1000, - DAC960_V4_CommandIdentifierRegisterOffset = 0x1001, - DAC960_V4_MailboxRegister2Offset = 0x1002, - DAC960_V4_MailboxRegister3Offset = 0x1003, - DAC960_V4_MailboxRegister4Offset = 0x1004, - DAC960_V4_MailboxRegister5Offset = 0x1005, - DAC960_V4_MailboxRegister6Offset = 0x1006, - DAC960_V4_MailboxRegister7Offset = 0x1007, - DAC960_V4_MailboxRegister8Offset = 0x1008, - DAC960_V4_MailboxRegister9Offset = 0x1009, - DAC960_V4_MailboxRegister10Offset = 0x100A, - DAC960_V4_MailboxRegister11Offset = 0x100B, - DAC960_V4_MailboxRegister12Offset = 0x100C, - DAC960_V4_StatusCommandIdentifierRegOffset = 0x1018, - DAC960_V4_StatusRegisterOffset = 0x101A, - DAC960_V4_ErrorStatusRegisterOffset = 0x103F + DAC960_PG_InboundDoorBellRegisterOffset = 0x0020, + DAC960_PG_OutboundDoorBellRegisterOffset = 0x002C, + DAC960_PG_InterruptMaskRegisterOffset = 0x0034, + DAC960_PG_CommandOpcodeRegisterOffset = 0x1000, + DAC960_PG_CommandIdentifierRegisterOffset = 0x1001, + DAC960_PG_MailboxRegister2Offset = 0x1002, + DAC960_PG_MailboxRegister3Offset = 0x1003, + DAC960_PG_MailboxRegister4Offset = 0x1004, + DAC960_PG_MailboxRegister5Offset = 0x1005, + DAC960_PG_MailboxRegister6Offset = 0x1006, + DAC960_PG_MailboxRegister7Offset = 0x1007, + DAC960_PG_MailboxRegister8Offset = 0x1008, + DAC960_PG_MailboxRegister9Offset = 0x1009, + DAC960_PG_MailboxRegister10Offset = 0x100A, + DAC960_PG_MailboxRegister11Offset = 0x100B, + DAC960_PG_MailboxRegister12Offset = 0x100C, + DAC960_PG_StatusCommandIdentifierRegOffset = 0x1018, + DAC960_PG_StatusRegisterOffset = 0x101A, + DAC960_PG_ErrorStatusRegisterOffset = 0x103F } -DAC960_V4_RegisterOffsets_T; +DAC960_PG_RegisterOffsets_T; /* - Define the structure of the DAC960 V4 Inbound Door Bell Register. + Define the structure of the DAC960 PG Series Inbound Door Bell Register. */ -typedef union DAC960_V4_InboundDoorBellRegister +typedef union DAC960_PG_InboundDoorBellRegister { unsigned int All; struct { @@ -1772,14 +3535,14 @@ typedef union DAC960_V4_InboundDoorBellRegister unsigned int :30; /* Bits 2-31 */ } Read; } -DAC960_V4_InboundDoorBellRegister_T; +DAC960_PG_InboundDoorBellRegister_T; /* - Define the structure of the DAC960 V4 Outbound Door Bell Register. + Define the structure of the DAC960 PG Series Outbound Door Bell Register. */ -typedef union DAC960_V4_OutboundDoorBellRegister +typedef union DAC960_PG_OutboundDoorBellRegister { unsigned int All; struct { @@ -1793,14 +3556,14 @@ typedef union DAC960_V4_OutboundDoorBellRegister unsigned int :30; /* Bits 2-31 */ } Read; } -DAC960_V4_OutboundDoorBellRegister_T; +DAC960_PG_OutboundDoorBellRegister_T; /* - Define the structure of the DAC960 V4 Interrupt Mask Register. + Define the structure of the DAC960 PG Series Interrupt Mask Register. */ -typedef union DAC960_V4_InterruptMaskRegister +typedef union DAC960_PG_InterruptMaskRegister { unsigned int All; struct { @@ -1810,14 +3573,14 @@ typedef union DAC960_V4_InterruptMaskRegister unsigned int Reserved0:24; /* Bits 8-31 */ } Bits; } -DAC960_V4_InterruptMaskRegister_T; +DAC960_PG_InterruptMaskRegister_T; /* - Define the structure of the DAC960 V4 Error Status Register. + Define the structure of the DAC960 PG Series Error Status Register. */ -typedef union DAC960_V4_ErrorStatusRegister +typedef union DAC960_PG_ErrorStatusRegister { unsigned char All; struct { @@ -1826,292 +3589,298 @@ typedef union DAC960_V4_ErrorStatusRegister unsigned int :5; /* Bits 3-7 */ } Bits; } -DAC960_V4_ErrorStatusRegister_T; +DAC960_PG_ErrorStatusRegister_T; /* Define inline functions to provide an abstraction for reading and writing the - DAC960 V4 Controller Interface Registers. + DAC960 PG Series Controller Interface Registers. */ static inline -void DAC960_V4_HardwareMailboxNewCommand(void *ControllerBaseAddress) +void DAC960_PG_HardwareMailboxNewCommand(void *ControllerBaseAddress) { - DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; InboundDoorBellRegister.Write.HardwareMailboxNewCommand = true; writel(InboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_PG_InboundDoorBellRegisterOffset); } static inline -void DAC960_V4_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress) +void DAC960_PG_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress) { - DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; InboundDoorBellRegister.Write.AcknowledgeHardwareMailboxStatus = true; writel(InboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_PG_InboundDoorBellRegisterOffset); } static inline -void DAC960_V4_GenerateInterrupt(void *ControllerBaseAddress) +void DAC960_PG_GenerateInterrupt(void *ControllerBaseAddress) { - DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; InboundDoorBellRegister.Write.GenerateInterrupt = true; writel(InboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_PG_InboundDoorBellRegisterOffset); } static inline -void DAC960_V4_ControllerReset(void *ControllerBaseAddress) +void DAC960_PG_ControllerReset(void *ControllerBaseAddress) { - DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; InboundDoorBellRegister.Write.ControllerReset = true; writel(InboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_PG_InboundDoorBellRegisterOffset); } static inline -void DAC960_V4_MemoryMailboxNewCommand(void *ControllerBaseAddress) +void DAC960_PG_MemoryMailboxNewCommand(void *ControllerBaseAddress) { - DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; InboundDoorBellRegister.Write.MemoryMailboxNewCommand = true; writel(InboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_PG_InboundDoorBellRegisterOffset); } static inline -boolean DAC960_V4_HardwareMailboxFullP(void *ControllerBaseAddress) +boolean DAC960_PG_HardwareMailboxFullP(void *ControllerBaseAddress) { - DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = - readl(ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset); + readl(ControllerBaseAddress + DAC960_PG_InboundDoorBellRegisterOffset); return InboundDoorBellRegister.Read.HardwareMailboxFull; } static inline -boolean DAC960_V4_InitializationInProgressP(void *ControllerBaseAddress) +boolean DAC960_PG_InitializationInProgressP(void *ControllerBaseAddress) { - DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = - readl(ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset); + readl(ControllerBaseAddress + DAC960_PG_InboundDoorBellRegisterOffset); return InboundDoorBellRegister.Read.InitializationInProgress; } static inline -void DAC960_V4_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress) +void DAC960_PG_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress) { - DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister; + DAC960_PG_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = 0; OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true; writel(OutboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V4_OutboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_PG_OutboundDoorBellRegisterOffset); } static inline -void DAC960_V4_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress) +void DAC960_PG_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress) { - DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister; + DAC960_PG_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = 0; OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true; writel(OutboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V4_OutboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_PG_OutboundDoorBellRegisterOffset); } static inline -void DAC960_V4_AcknowledgeInterrupt(void *ControllerBaseAddress) +void DAC960_PG_AcknowledgeInterrupt(void *ControllerBaseAddress) { - DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister; + DAC960_PG_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = 0; OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true; OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true; writel(OutboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V4_OutboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_PG_OutboundDoorBellRegisterOffset); } static inline -boolean DAC960_V4_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress) +boolean DAC960_PG_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress) { - DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister; + DAC960_PG_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = - readl(ControllerBaseAddress + DAC960_V4_OutboundDoorBellRegisterOffset); + readl(ControllerBaseAddress + DAC960_PG_OutboundDoorBellRegisterOffset); return OutboundDoorBellRegister.Read.HardwareMailboxStatusAvailable; } static inline -boolean DAC960_V4_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress) +boolean DAC960_PG_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress) { - DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister; + DAC960_PG_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = - readl(ControllerBaseAddress + DAC960_V4_OutboundDoorBellRegisterOffset); + readl(ControllerBaseAddress + DAC960_PG_OutboundDoorBellRegisterOffset); return OutboundDoorBellRegister.Read.MemoryMailboxStatusAvailable; } static inline -void DAC960_V4_EnableInterrupts(void *ControllerBaseAddress) +void DAC960_PG_EnableInterrupts(void *ControllerBaseAddress) { - DAC960_V4_InterruptMaskRegister_T InterruptMaskRegister; + DAC960_PG_InterruptMaskRegister_T InterruptMaskRegister; InterruptMaskRegister.All = 0; InterruptMaskRegister.Bits.MessageUnitInterruptMask1 = 0x3; InterruptMaskRegister.Bits.DisableInterrupts = false; InterruptMaskRegister.Bits.MessageUnitInterruptMask2 = 0x1F; writel(InterruptMaskRegister.All, - ControllerBaseAddress + DAC960_V4_InterruptMaskRegisterOffset); + ControllerBaseAddress + DAC960_PG_InterruptMaskRegisterOffset); } static inline -void DAC960_V4_DisableInterrupts(void *ControllerBaseAddress) +void DAC960_PG_DisableInterrupts(void *ControllerBaseAddress) { - DAC960_V4_InterruptMaskRegister_T InterruptMaskRegister; + DAC960_PG_InterruptMaskRegister_T InterruptMaskRegister; InterruptMaskRegister.All = 0; InterruptMaskRegister.Bits.MessageUnitInterruptMask1 = 0x3; InterruptMaskRegister.Bits.DisableInterrupts = true; InterruptMaskRegister.Bits.MessageUnitInterruptMask2 = 0x1F; writel(InterruptMaskRegister.All, - ControllerBaseAddress + DAC960_V4_InterruptMaskRegisterOffset); + ControllerBaseAddress + DAC960_PG_InterruptMaskRegisterOffset); } static inline -boolean DAC960_V4_InterruptsEnabledP(void *ControllerBaseAddress) +boolean DAC960_PG_InterruptsEnabledP(void *ControllerBaseAddress) { - DAC960_V4_InterruptMaskRegister_T InterruptMaskRegister; + DAC960_PG_InterruptMaskRegister_T InterruptMaskRegister; InterruptMaskRegister.All = - readl(ControllerBaseAddress + DAC960_V4_InterruptMaskRegisterOffset); + readl(ControllerBaseAddress + DAC960_PG_InterruptMaskRegisterOffset); return !InterruptMaskRegister.Bits.DisableInterrupts; } static inline -void DAC960_V4_WriteCommandMailbox(DAC960_CommandMailbox_T *NextCommandMailbox, - DAC960_CommandMailbox_T *CommandMailbox) +void DAC960_PG_WriteCommandMailbox(DAC960_V1_CommandMailbox_T + *MemoryCommandMailbox, + DAC960_V1_CommandMailbox_T + *CommandMailbox) { - NextCommandMailbox->Words[1] = CommandMailbox->Words[1]; - NextCommandMailbox->Words[2] = CommandMailbox->Words[2]; - NextCommandMailbox->Words[3] = CommandMailbox->Words[3]; + MemoryCommandMailbox->Words[1] = CommandMailbox->Words[1]; + MemoryCommandMailbox->Words[2] = CommandMailbox->Words[2]; + MemoryCommandMailbox->Words[3] = CommandMailbox->Words[3]; wmb(); - NextCommandMailbox->Words[0] = CommandMailbox->Words[0]; + MemoryCommandMailbox->Words[0] = CommandMailbox->Words[0]; mb(); } static inline -void DAC960_V4_WriteHardwareMailbox(void *ControllerBaseAddress, - DAC960_CommandMailbox_T *CommandMailbox) +void DAC960_PG_WriteHardwareMailbox(void *ControllerBaseAddress, + DAC960_V1_CommandMailbox_T *CommandMailbox) { writel(CommandMailbox->Words[0], - ControllerBaseAddress + DAC960_V4_CommandOpcodeRegisterOffset); + ControllerBaseAddress + DAC960_PG_CommandOpcodeRegisterOffset); writel(CommandMailbox->Words[1], - ControllerBaseAddress + DAC960_V4_MailboxRegister4Offset); + ControllerBaseAddress + DAC960_PG_MailboxRegister4Offset); writel(CommandMailbox->Words[2], - ControllerBaseAddress + DAC960_V4_MailboxRegister8Offset); + ControllerBaseAddress + DAC960_PG_MailboxRegister8Offset); writeb(CommandMailbox->Bytes[12], - ControllerBaseAddress + DAC960_V4_MailboxRegister12Offset); + ControllerBaseAddress + DAC960_PG_MailboxRegister12Offset); } -static inline DAC960_CommandIdentifier_T -DAC960_V4_ReadStatusCommandIdentifier(void *ControllerBaseAddress) +static inline DAC960_V1_CommandIdentifier_T +DAC960_PG_ReadStatusCommandIdentifier(void *ControllerBaseAddress) { return readb(ControllerBaseAddress - + DAC960_V4_StatusCommandIdentifierRegOffset); + + DAC960_PG_StatusCommandIdentifierRegOffset); } -static inline DAC960_CommandStatus_T -DAC960_V4_ReadStatusRegister(void *ControllerBaseAddress) +static inline DAC960_V1_CommandStatus_T +DAC960_PG_ReadStatusRegister(void *ControllerBaseAddress) { - return readw(ControllerBaseAddress + DAC960_V4_StatusRegisterOffset); + return readw(ControllerBaseAddress + DAC960_PG_StatusRegisterOffset); } static inline boolean -DAC960_V4_ReadErrorStatus(void *ControllerBaseAddress, +DAC960_PG_ReadErrorStatus(void *ControllerBaseAddress, unsigned char *ErrorStatus, unsigned char *Parameter0, unsigned char *Parameter1) { - DAC960_V4_ErrorStatusRegister_T ErrorStatusRegister; + DAC960_PG_ErrorStatusRegister_T ErrorStatusRegister; ErrorStatusRegister.All = - readb(ControllerBaseAddress + DAC960_V4_ErrorStatusRegisterOffset); + readb(ControllerBaseAddress + DAC960_PG_ErrorStatusRegisterOffset); if (!ErrorStatusRegister.Bits.ErrorStatusPending) return false; ErrorStatusRegister.Bits.ErrorStatusPending = false; *ErrorStatus = ErrorStatusRegister.All; *Parameter0 = - readb(ControllerBaseAddress + DAC960_V4_CommandOpcodeRegisterOffset); + readb(ControllerBaseAddress + DAC960_PG_CommandOpcodeRegisterOffset); *Parameter1 = - readb(ControllerBaseAddress + DAC960_V4_CommandIdentifierRegisterOffset); - writeb(0, ControllerBaseAddress + DAC960_V4_ErrorStatusRegisterOffset); + readb(ControllerBaseAddress + DAC960_PG_CommandIdentifierRegisterOffset); + writeb(0, ControllerBaseAddress + DAC960_PG_ErrorStatusRegisterOffset); return true; } static inline -void DAC960_V4_SaveMemoryMailboxInfo(DAC960_Controller_T *Controller) +void DAC960_PG_SaveMemoryMailboxInfo(DAC960_Controller_T *Controller) { +#ifdef __i386__ void *ControllerBaseAddress = Controller->BaseAddress; writel(0x743C485E, - ControllerBaseAddress + DAC960_V4_CommandOpcodeRegisterOffset); - writel((unsigned long) Controller->FirstCommandMailbox, - ControllerBaseAddress + DAC960_V4_MailboxRegister4Offset); - writew(Controller->NextCommandMailbox - Controller->FirstCommandMailbox, - ControllerBaseAddress + DAC960_V4_MailboxRegister8Offset); - writew(Controller->NextStatusMailbox - Controller->FirstStatusMailbox, - ControllerBaseAddress + DAC960_V4_MailboxRegister10Offset); + ControllerBaseAddress + DAC960_PG_CommandOpcodeRegisterOffset); + writel((unsigned long) Controller->V1.FirstCommandMailbox, + ControllerBaseAddress + DAC960_PG_MailboxRegister4Offset); + writew(Controller->V1.NextCommandMailbox - Controller->V1.FirstCommandMailbox, + ControllerBaseAddress + DAC960_PG_MailboxRegister8Offset); + writew(Controller->V1.NextStatusMailbox - Controller->V1.FirstStatusMailbox, + ControllerBaseAddress + DAC960_PG_MailboxRegister10Offset); +#endif } static inline -void DAC960_V4_RestoreMemoryMailboxInfo(DAC960_Controller_T *Controller, +void DAC960_PG_RestoreMemoryMailboxInfo(DAC960_Controller_T *Controller, void **MemoryMailboxAddress, short *NextCommandMailboxIndex, short *NextStatusMailboxIndex) { +#ifdef __i386__ void *ControllerBaseAddress = Controller->BaseAddress; if (readl(ControllerBaseAddress - + DAC960_V4_CommandOpcodeRegisterOffset) != 0x743C485E) + + DAC960_PG_CommandOpcodeRegisterOffset) != 0x743C485E) return; *MemoryMailboxAddress = - (void *) readl(ControllerBaseAddress + DAC960_V4_MailboxRegister4Offset); + (void *) readl(ControllerBaseAddress + DAC960_PG_MailboxRegister4Offset); *NextCommandMailboxIndex = - readw(ControllerBaseAddress + DAC960_V4_MailboxRegister8Offset); + readw(ControllerBaseAddress + DAC960_PG_MailboxRegister8Offset); *NextStatusMailboxIndex = - readw(ControllerBaseAddress + DAC960_V4_MailboxRegister10Offset); + readw(ControllerBaseAddress + DAC960_PG_MailboxRegister10Offset); +#endif } /* - Define the DAC960 V3 Controller Interface Register Offsets. + Define the DAC960 PD Series Controller Interface Register Offsets. */ -#define DAC960_V3_RegisterWindowSize 0x80 +#define DAC960_PD_RegisterWindowSize 0x80 typedef enum { - DAC960_V3_CommandOpcodeRegisterOffset = 0x00, - DAC960_V3_CommandIdentifierRegisterOffset = 0x01, - DAC960_V3_MailboxRegister2Offset = 0x02, - DAC960_V3_MailboxRegister3Offset = 0x03, - DAC960_V3_MailboxRegister4Offset = 0x04, - DAC960_V3_MailboxRegister5Offset = 0x05, - DAC960_V3_MailboxRegister6Offset = 0x06, - DAC960_V3_MailboxRegister7Offset = 0x07, - DAC960_V3_MailboxRegister8Offset = 0x08, - DAC960_V3_MailboxRegister9Offset = 0x09, - DAC960_V3_MailboxRegister10Offset = 0x0A, - DAC960_V3_MailboxRegister11Offset = 0x0B, - DAC960_V3_MailboxRegister12Offset = 0x0C, - DAC960_V3_StatusCommandIdentifierRegOffset = 0x0D, - DAC960_V3_StatusRegisterOffset = 0x0E, - DAC960_V3_ErrorStatusRegisterOffset = 0x3F, - DAC960_V3_InboundDoorBellRegisterOffset = 0x40, - DAC960_V3_OutboundDoorBellRegisterOffset = 0x41, - DAC960_V3_InterruptEnableRegisterOffset = 0x43 + DAC960_PD_CommandOpcodeRegisterOffset = 0x00, + DAC960_PD_CommandIdentifierRegisterOffset = 0x01, + DAC960_PD_MailboxRegister2Offset = 0x02, + DAC960_PD_MailboxRegister3Offset = 0x03, + DAC960_PD_MailboxRegister4Offset = 0x04, + DAC960_PD_MailboxRegister5Offset = 0x05, + DAC960_PD_MailboxRegister6Offset = 0x06, + DAC960_PD_MailboxRegister7Offset = 0x07, + DAC960_PD_MailboxRegister8Offset = 0x08, + DAC960_PD_MailboxRegister9Offset = 0x09, + DAC960_PD_MailboxRegister10Offset = 0x0A, + DAC960_PD_MailboxRegister11Offset = 0x0B, + DAC960_PD_MailboxRegister12Offset = 0x0C, + DAC960_PD_StatusCommandIdentifierRegOffset = 0x0D, + DAC960_PD_StatusRegisterOffset = 0x0E, + DAC960_PD_ErrorStatusRegisterOffset = 0x3F, + DAC960_PD_InboundDoorBellRegisterOffset = 0x40, + DAC960_PD_OutboundDoorBellRegisterOffset = 0x41, + DAC960_PD_InterruptEnableRegisterOffset = 0x43 } -DAC960_V3_RegisterOffsets_T; +DAC960_PD_RegisterOffsets_T; /* - Define the structure of the DAC960 V3 Inbound Door Bell Register. + Define the structure of the DAC960 PD Series Inbound Door Bell Register. */ -typedef union DAC960_V3_InboundDoorBellRegister +typedef union DAC960_PD_InboundDoorBellRegister { unsigned char All; struct { @@ -2127,14 +3896,14 @@ typedef union DAC960_V3_InboundDoorBellRegister unsigned char :6; /* Bits 2-7 */ } Read; } -DAC960_V3_InboundDoorBellRegister_T; +DAC960_PD_InboundDoorBellRegister_T; /* - Define the structure of the DAC960 V3 Outbound Door Bell Register. + Define the structure of the DAC960 PD Series Outbound Door Bell Register. */ -typedef union DAC960_V3_OutboundDoorBellRegister +typedef union DAC960_PD_OutboundDoorBellRegister { unsigned char All; struct { @@ -2146,14 +3915,14 @@ typedef union DAC960_V3_OutboundDoorBellRegister unsigned char :7; /* Bits 1-7 */ } Read; } -DAC960_V3_OutboundDoorBellRegister_T; +DAC960_PD_OutboundDoorBellRegister_T; /* - Define the structure of the DAC960 V3 Interrupt Enable Register. + Define the structure of the DAC960 PD Series Interrupt Enable Register. */ -typedef union DAC960_V3_InterruptEnableRegister +typedef union DAC960_PD_InterruptEnableRegister { unsigned char All; struct { @@ -2161,14 +3930,14 @@ typedef union DAC960_V3_InterruptEnableRegister unsigned char :7; /* Bits 1-7 */ } Bits; } -DAC960_V3_InterruptEnableRegister_T; +DAC960_PD_InterruptEnableRegister_T; /* - Define the structure of the DAC960 V3 Error Status Register. + Define the structure of the DAC960 PD Series Error Status Register. */ -typedef union DAC960_V3_ErrorStatusRegister +typedef union DAC960_PD_ErrorStatusRegister { unsigned char All; struct { @@ -2177,204 +3946,190 @@ typedef union DAC960_V3_ErrorStatusRegister unsigned int :5; /* Bits 3-7 */ } Bits; } -DAC960_V3_ErrorStatusRegister_T; +DAC960_PD_ErrorStatusRegister_T; /* Define inline functions to provide an abstraction for reading and writing the - DAC960 V3 Controller Interface Registers. + DAC960 PD Series Controller Interface Registers. */ static inline -void DAC960_V3_NewCommand(void *ControllerBaseAddress) +void DAC960_PD_NewCommand(void *ControllerBaseAddress) { - DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; InboundDoorBellRegister.Write.NewCommand = true; writeb(InboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_PD_InboundDoorBellRegisterOffset); } static inline -void DAC960_V3_AcknowledgeStatus(void *ControllerBaseAddress) +void DAC960_PD_AcknowledgeStatus(void *ControllerBaseAddress) { - DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; InboundDoorBellRegister.Write.AcknowledgeStatus = true; writeb(InboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_PD_InboundDoorBellRegisterOffset); } static inline -void DAC960_V3_GenerateInterrupt(void *ControllerBaseAddress) +void DAC960_PD_GenerateInterrupt(void *ControllerBaseAddress) { - DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; InboundDoorBellRegister.Write.GenerateInterrupt = true; writeb(InboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_PD_InboundDoorBellRegisterOffset); } static inline -void DAC960_V3_ControllerReset(void *ControllerBaseAddress) +void DAC960_PD_ControllerReset(void *ControllerBaseAddress) { - DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = 0; InboundDoorBellRegister.Write.ControllerReset = true; writeb(InboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_PD_InboundDoorBellRegisterOffset); } static inline -boolean DAC960_V3_MailboxFullP(void *ControllerBaseAddress) +boolean DAC960_PD_MailboxFullP(void *ControllerBaseAddress) { - DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = - readb(ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset); + readb(ControllerBaseAddress + DAC960_PD_InboundDoorBellRegisterOffset); return InboundDoorBellRegister.Read.MailboxFull; } static inline -boolean DAC960_V3_InitializationInProgressP(void *ControllerBaseAddress) +boolean DAC960_PD_InitializationInProgressP(void *ControllerBaseAddress) { - DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister; + DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = - readb(ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset); + readb(ControllerBaseAddress + DAC960_PD_InboundDoorBellRegisterOffset); return InboundDoorBellRegister.Read.InitializationInProgress; } static inline -void DAC960_V3_AcknowledgeInterrupt(void *ControllerBaseAddress) +void DAC960_PD_AcknowledgeInterrupt(void *ControllerBaseAddress) { - DAC960_V3_OutboundDoorBellRegister_T OutboundDoorBellRegister; + DAC960_PD_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = 0; OutboundDoorBellRegister.Write.AcknowledgeInterrupt = true; writeb(OutboundDoorBellRegister.All, - ControllerBaseAddress + DAC960_V3_OutboundDoorBellRegisterOffset); + ControllerBaseAddress + DAC960_PD_OutboundDoorBellRegisterOffset); } static inline -boolean DAC960_V3_StatusAvailableP(void *ControllerBaseAddress) +boolean DAC960_PD_StatusAvailableP(void *ControllerBaseAddress) { - DAC960_V3_OutboundDoorBellRegister_T OutboundDoorBellRegister; + DAC960_PD_OutboundDoorBellRegister_T OutboundDoorBellRegister; OutboundDoorBellRegister.All = - readb(ControllerBaseAddress + DAC960_V3_OutboundDoorBellRegisterOffset); + readb(ControllerBaseAddress + DAC960_PD_OutboundDoorBellRegisterOffset); return OutboundDoorBellRegister.Read.StatusAvailable; } static inline -void DAC960_V3_EnableInterrupts(void *ControllerBaseAddress) +void DAC960_PD_EnableInterrupts(void *ControllerBaseAddress) { - DAC960_V3_InterruptEnableRegister_T InterruptEnableRegister; + DAC960_PD_InterruptEnableRegister_T InterruptEnableRegister; InterruptEnableRegister.All = 0; InterruptEnableRegister.Bits.EnableInterrupts = true; writeb(InterruptEnableRegister.All, - ControllerBaseAddress + DAC960_V3_InterruptEnableRegisterOffset); + ControllerBaseAddress + DAC960_PD_InterruptEnableRegisterOffset); } static inline -void DAC960_V3_DisableInterrupts(void *ControllerBaseAddress) +void DAC960_PD_DisableInterrupts(void *ControllerBaseAddress) { - DAC960_V3_InterruptEnableRegister_T InterruptEnableRegister; + DAC960_PD_InterruptEnableRegister_T InterruptEnableRegister; InterruptEnableRegister.All = 0; InterruptEnableRegister.Bits.EnableInterrupts = false; writeb(InterruptEnableRegister.All, - ControllerBaseAddress + DAC960_V3_InterruptEnableRegisterOffset); + ControllerBaseAddress + DAC960_PD_InterruptEnableRegisterOffset); } static inline -boolean DAC960_V3_InterruptsEnabledP(void *ControllerBaseAddress) +boolean DAC960_PD_InterruptsEnabledP(void *ControllerBaseAddress) { - DAC960_V3_InterruptEnableRegister_T InterruptEnableRegister; + DAC960_PD_InterruptEnableRegister_T InterruptEnableRegister; InterruptEnableRegister.All = - readb(ControllerBaseAddress + DAC960_V3_InterruptEnableRegisterOffset); + readb(ControllerBaseAddress + DAC960_PD_InterruptEnableRegisterOffset); return InterruptEnableRegister.Bits.EnableInterrupts; } static inline -void DAC960_V3_WriteCommandMailbox(void *ControllerBaseAddress, - DAC960_CommandMailbox_T *CommandMailbox) +void DAC960_PD_WriteCommandMailbox(void *ControllerBaseAddress, + DAC960_V1_CommandMailbox_T *CommandMailbox) { writel(CommandMailbox->Words[0], - ControllerBaseAddress + DAC960_V3_CommandOpcodeRegisterOffset); + ControllerBaseAddress + DAC960_PD_CommandOpcodeRegisterOffset); writel(CommandMailbox->Words[1], - ControllerBaseAddress + DAC960_V3_MailboxRegister4Offset); + ControllerBaseAddress + DAC960_PD_MailboxRegister4Offset); writel(CommandMailbox->Words[2], - ControllerBaseAddress + DAC960_V3_MailboxRegister8Offset); + ControllerBaseAddress + DAC960_PD_MailboxRegister8Offset); writeb(CommandMailbox->Bytes[12], - ControllerBaseAddress + DAC960_V3_MailboxRegister12Offset); + ControllerBaseAddress + DAC960_PD_MailboxRegister12Offset); } -static inline DAC960_CommandIdentifier_T -DAC960_V3_ReadStatusCommandIdentifier(void *ControllerBaseAddress) +static inline DAC960_V1_CommandIdentifier_T +DAC960_PD_ReadStatusCommandIdentifier(void *ControllerBaseAddress) { return readb(ControllerBaseAddress - + DAC960_V3_StatusCommandIdentifierRegOffset); + + DAC960_PD_StatusCommandIdentifierRegOffset); } -static inline DAC960_CommandStatus_T -DAC960_V3_ReadStatusRegister(void *ControllerBaseAddress) +static inline DAC960_V1_CommandStatus_T +DAC960_PD_ReadStatusRegister(void *ControllerBaseAddress) { - return readw(ControllerBaseAddress + DAC960_V3_StatusRegisterOffset); + return readw(ControllerBaseAddress + DAC960_PD_StatusRegisterOffset); } static inline boolean -DAC960_V3_ReadErrorStatus(void *ControllerBaseAddress, +DAC960_PD_ReadErrorStatus(void *ControllerBaseAddress, unsigned char *ErrorStatus, unsigned char *Parameter0, unsigned char *Parameter1) { - DAC960_V3_ErrorStatusRegister_T ErrorStatusRegister; + DAC960_PD_ErrorStatusRegister_T ErrorStatusRegister; ErrorStatusRegister.All = - readb(ControllerBaseAddress + DAC960_V3_ErrorStatusRegisterOffset); + readb(ControllerBaseAddress + DAC960_PD_ErrorStatusRegisterOffset); if (!ErrorStatusRegister.Bits.ErrorStatusPending) return false; ErrorStatusRegister.Bits.ErrorStatusPending = false; *ErrorStatus = ErrorStatusRegister.All; *Parameter0 = - readb(ControllerBaseAddress + DAC960_V3_CommandOpcodeRegisterOffset); + readb(ControllerBaseAddress + DAC960_PD_CommandOpcodeRegisterOffset); *Parameter1 = - readb(ControllerBaseAddress + DAC960_V3_CommandIdentifierRegisterOffset); - writeb(0, ControllerBaseAddress + DAC960_V3_ErrorStatusRegisterOffset); + readb(ControllerBaseAddress + DAC960_PD_CommandIdentifierRegisterOffset); + writeb(0, ControllerBaseAddress + DAC960_PD_ErrorStatusRegisterOffset); return true; } /* - Define compatibility macros between Linux 2.0 and Linux 2.1. -*/ - -#if LINUX_VERSION_CODE < 0x20100 - -#define MODULE_PARM(Variable, Type) -#define ioremap_nocache(Offset, Size) vremap(Offset, Size) -#define iounmap(Address) vfree(Address) - -#endif - - -/* Define prototypes for the forward referenced DAC960 Driver Internal Functions. */ static void DAC960_FinalizeController(DAC960_Controller_T *); static int DAC960_Finalize(NotifierBlock_T *, unsigned long, void *); -static void DAC960_RequestFunction0(request_queue_t *); -static void DAC960_RequestFunction1(request_queue_t *); -static void DAC960_RequestFunction2(request_queue_t *); -static void DAC960_RequestFunction3(request_queue_t *); -static void DAC960_RequestFunction4(request_queue_t *); -static void DAC960_RequestFunction5(request_queue_t *); -static void DAC960_RequestFunction6(request_queue_t *); -static void DAC960_RequestFunction7(request_queue_t *); -static void DAC960_InterruptHandler(int, void *, Registers_T *); -static void DAC960_QueueMonitoringCommand(DAC960_Command_T *); +static void DAC960_V1_QueueReadWriteCommand(DAC960_Command_T *); +static void DAC960_V2_QueueReadWriteCommand(DAC960_Command_T *); +static void DAC960_RequestFunction(RequestQueue_T *); +static void DAC960_BA_InterruptHandler(int, void *, Registers_T *); +static void DAC960_LP_InterruptHandler(int, void *, Registers_T *); +static void DAC960_LA_InterruptHandler(int, void *, Registers_T *); +static void DAC960_PG_InterruptHandler(int, void *, Registers_T *); +static void DAC960_PD_InterruptHandler(int, void *, Registers_T *); +static void DAC960_V1_QueueMonitoringCommand(DAC960_Command_T *); +static void DAC960_V2_QueueMonitoringCommand(DAC960_Command_T *); static void DAC960_MonitoringTimerFunction(unsigned long); static int DAC960_Open(Inode_T *, File_T *); static int DAC960_Release(Inode_T *, File_T *); static int DAC960_IOCTL(Inode_T *, File_T *, unsigned int, unsigned long); static int DAC960_UserIOCTL(Inode_T *, File_T *, unsigned int, unsigned long); -static void DAC960_InitializeGenericDiskInfo(GenericDiskInfo_T *); -static void DAC960_Message(DAC960_MessageLevel_T, char *, +static void DAC960_Message(DAC960_MessageLevel_T, unsigned char *, DAC960_Controller_T *, ...); static void DAC960_CreateProcEntries(void); static void DAC960_DestroyProcEntries(void); diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 8d0d245b3..fd36f06c4 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -9,7 +9,7 @@ * * The bridge optimization stuff has been removed. If you really * have a silly BIOS which is unable to set your host bridge right, - * use the PowerTweak utility (see http://linux.powertweak.com/). + * use the PowerTweak utility (see http://powertweak.sourceforge.net). */ #include <linux/types.h> diff --git a/fs/buffer.c b/fs/buffer.c index ad0a04e68..e6134c203 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -839,6 +839,7 @@ repeat: out: write_unlock(&hash_table_lock); spin_unlock(&lru_list_lock); + touch_buffer(bh); return bh; } diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 678eb4d28..5dfe2cf55 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -18,8 +18,6 @@ * David S. Miller (davem@caip.rutgers.edu), 1995 * 64-bit file support on 64-bit platforms by Jakub Jelinek * (jj@sunsite.ms.mff.cuni.cz) - * - * Assorted race fixes, rewrite of ext2_get_block() by Al Viro, 2000 */ #include <linux/fs.h> @@ -28,6 +26,8 @@ #include <linux/sched.h> #include <linux/highuid.h> + + static int ext2_update_inode(struct inode * inode, int do_sync); /* @@ -64,18 +64,23 @@ no_delete: clear_inode(inode); /* We must guarantee clearing of inode... */ } +/* + * ext2_discard_prealloc and ext2_alloc_block are atomic wrt. the + * superblock in the same manner as are ext2_free_blocks and + * ext2_new_block. We just wait on the super rather than locking it + * here, since ext2_new_block will do the necessary locking and we + * can't block until then. + */ void ext2_discard_prealloc (struct inode * inode) { #ifdef EXT2_PREALLOCATE + unsigned short total; + lock_kernel(); - /* Writer: ->i_prealloc* */ if (inode->u.ext2_i.i_prealloc_count) { - unsigned short total = inode->u.ext2_i.i_prealloc_count; - unsigned long block = inode->u.ext2_i.i_prealloc_block; + total = inode->u.ext2_i.i_prealloc_count; inode->u.ext2_i.i_prealloc_count = 0; - inode->u.ext2_i.i_prealloc_block = 0; - /* Writer: end */ - ext2_free_blocks (inode, block, total); + ext2_free_blocks (inode, inode->u.ext2_i.i_prealloc_block, total); } unlock_kernel(); #endif @@ -88,26 +93,22 @@ static int ext2_alloc_block (struct inode * inode, unsigned long goal, int *err) #endif unsigned long result; + wait_on_super (inode->i_sb); #ifdef EXT2_PREALLOCATE - /* Writer: ->i_prealloc* */ if (inode->u.ext2_i.i_prealloc_count && (goal == inode->u.ext2_i.i_prealloc_block || goal + 1 == inode->u.ext2_i.i_prealloc_block)) { result = inode->u.ext2_i.i_prealloc_block++; inode->u.ext2_i.i_prealloc_count--; - /* Writer: end */ -#ifdef EXT2FS_DEBUG ext2_debug ("preallocation hit (%lu/%lu).\n", ++alloc_hits, ++alloc_attempts); -#endif + } else { ext2_discard_prealloc (inode); -#ifdef EXT2FS_DEBUG ext2_debug ("preallocation miss (%lu/%lu).\n", alloc_hits, ++alloc_attempts); -#endif if (S_ISREG(inode->i_mode)) result = ext2_new_block (inode, goal, &inode->u.ext2_i.i_prealloc_count, @@ -298,307 +299,307 @@ no_block: return p; } -/** - * ext2_find_near - find a place for allocation with sufficient locality - * @inode: owner - * @ind: descriptor of indirect block. - * - * This function returns the prefered place for block allocation. - * It is used when heuristic for sequential allocation fails. - * Rules are: - * + if there is a block to the left of our position - allocate near it. - * + if pointer will live in indirect block - allocate near that block. - * + if pointer will live in inode - allocate in the same cylinder group. - * Caller must make sure that @ind is valid and will stay that way. - */ - -static inline unsigned long ext2_find_near(struct inode *inode, Indirect *ind) +static struct buffer_head * inode_getblk (struct inode * inode, int nr, + int new_block, int * err, int metadata, long *phys, int *new) { - u32 *start = ind->bh ? (u32*) ind->bh->b_data : inode->u.ext2_i.i_data; - u32 *p; - - /* Try to find previous block */ - for (p = ind->p - 1; p >= start; p--) - if (*p) - return le32_to_cpu(*p); - - /* No such thing, so let's try location of indirect block */ - if (ind->bh) - return ind->bh->b_blocknr; + u32 * p; + int tmp, goal = 0; + struct buffer_head * result; + int blocksize = inode->i_sb->s_blocksize; - /* - * It is going to be refered from inode itself? OK, just put it into - * the same cylinder group then. - */ - return (inode->u.ext2_i.i_block_group * - EXT2_BLOCKS_PER_GROUP(inode->i_sb)) + - le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_first_data_block); -} + p = inode->u.ext2_i.i_data + nr; +repeat: + tmp = le32_to_cpu(*p); + if (tmp) { + if (metadata) { + result = getblk (inode->i_dev, tmp, blocksize); + if (tmp == le32_to_cpu(*p)) + return result; + brelse (result); + goto repeat; + } else { + *phys = tmp; + return NULL; + } + } -/** - * ext2_find_goal - find a prefered place for allocation. - * @inode: owner - * @block: block we want - * @chain: chain of indirect blocks - * @partial: pointer to the last triple within a chain. - * - * This function returns the prefered place for block allocation. - */ + if (inode->u.ext2_i.i_next_alloc_block == new_block) + goal = inode->u.ext2_i.i_next_alloc_goal; -static inline unsigned long ext2_find_goal(struct inode *inode, - long block, - Indirect chain[4], - Indirect *partial) -{ - unsigned long goal = 0; + ext2_debug ("hint = %d,", goal); - /* Writer: ->i_next_alloc* */ - if (block == inode->u.ext2_i.i_next_alloc_block + 1) { - inode->u.ext2_i.i_next_alloc_block++; - inode->u.ext2_i.i_next_alloc_goal++; - } - /* Writer: end */ - /* Reader: pointers, ->i_next_alloc* */ - if (verify_chain(chain, partial)) { - /* - * try the heuristic for sequential allocation, - * failing that at least try to get decent locality. - */ - if (block == inode->u.ext2_i.i_next_alloc_block) - goal = inode->u.ext2_i.i_next_alloc_goal; + if (!goal) { + for (tmp = nr - 1; tmp >= 0; tmp--) { + if (inode->u.ext2_i.i_data[tmp]) { + goal = le32_to_cpu(inode->u.ext2_i.i_data[tmp]); + break; + } + } if (!goal) - goal = ext2_find_near(inode, partial); + goal = (inode->u.ext2_i.i_block_group * + EXT2_BLOCKS_PER_GROUP(inode->i_sb)) + + le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_first_data_block); } - /* Reader: end */ - return goal; -} -/** - * ext2_alloc_branch - allocate and set up a chain of blocks. - * @inode: owner - * @num: depth of the chain (number of blocks to allocate) - * @offsets: offsets (in the blocks) to store the pointers to next. - * @branch: place to store the chain in. - * - * This function allocates @num blocks, zeroes out all but the last one, - * links them into chain and (if we are synchronous) writes them to disk. - * In other words, it prepares a branch that can be spliced onto the - * inode. It stores the information about that chain in the branch[], in - * the same format as ext2_get_branch() would do. We are calling it after - * we had read the existing part of chain and partial points to the last - * triple of that (one with zero ->key). Upon the exit we have the same - * picture as after the successful ext2_get_block(), excpet that in one - * place chain is disconnected - *branch->p is still zero (we did not - * set the last link), but branch->key contains the number that should - * be placed into *branch->p to fill that gap. - * - * If allocation fails we free all blocks we've allocated (and forget - * ther buffer_heads) and return the error value the from failed - * ext2_alloc_block() (normally -ENOSPC). Otherwise we set the chain - * as described above and return 0. - */ - -static int ext2_alloc_branch(struct inode *inode, - int num, - unsigned long goal, - int *offsets, - Indirect *branch) -{ - int blocksize = inode->i_sb->s_blocksize; - int n = 0; - int err; - int i; - int parent = ext2_alloc_block(inode, goal, &err); - - branch[0].key = cpu_to_le32(parent); - if (parent) for (n = 1; n < num; n++) { - struct buffer_head *bh; - /* Allocate the next block */ - int nr = ext2_alloc_block(inode, parent, &err); - if (!nr) - break; - branch[n].key = cpu_to_le32(nr); - /* - * Get buffer_head for parent block, zero it out and set - * the pointer to new one, then send parent to disk. - */ - bh = getblk(inode->i_dev, parent, blocksize); - if (!buffer_uptodate(bh)) - wait_on_buffer(bh); - memset(bh->b_data, 0, blocksize); - branch[n].bh = bh; - branch[n].p = (u32*) bh->b_data + offsets[n]; - *branch[n].p = branch[n].key; - mark_buffer_uptodate(bh, 1); - mark_buffer_dirty(bh, 1); - if (IS_SYNC(inode) || inode->u.ext2_i.i_osync) { - ll_rw_block (WRITE, 1, &bh); - wait_on_buffer (bh); + ext2_debug ("goal = %d.\n", goal); + + tmp = ext2_alloc_block (inode, goal, err); + if (!tmp) + return NULL; + + if (metadata) { + result = getblk (inode->i_dev, tmp, blocksize); + if (!buffer_uptodate(result)) + wait_on_buffer(result); + memset(result->b_data, 0, blocksize); + mark_buffer_uptodate(result, 1); + mark_buffer_dirty(result, 1); + if (*p) { + ext2_free_blocks (inode, tmp, 1); + bforget (result); + goto repeat; } - parent = nr; + } else { + if (*p) { + /* + * Nobody is allowed to change block allocation + * state from under us: + */ + ext2_error (inode->i_sb, "block_getblk", + "data block filled under us"); + BUG(); + ext2_free_blocks (inode, tmp, 1); + goto repeat; + } + *phys = tmp; + result = NULL; + *err = 0; + *new = 1; } - if (n == num) - return 0; + *p = cpu_to_le32(tmp); - /* Allocation failed, free what we already allocated */ - for (i = 1; i < n; i++) - bforget(branch[i].bh); - for (i = 0; i < n; i++) - ext2_free_blocks(inode, le32_to_cpu(branch[i].key), 1); - return err; + inode->u.ext2_i.i_next_alloc_block = new_block; + inode->u.ext2_i.i_next_alloc_goal = tmp; + inode->i_ctime = CURRENT_TIME; + inode->i_blocks += blocksize/512; + if (IS_SYNC(inode) || inode->u.ext2_i.i_osync) + ext2_sync_inode (inode); + else + mark_inode_dirty(inode); + return result; } -/** - * ext2_splice_branch - splice the allocated branch onto inode. - * @inode: owner - * @block: (logical) number of block we are adding - * @chain: chain of indirect blocks (with a missing link - see - * ext2_alloc_branch) - * @where: location of missing link - * @num: number of blocks we are adding +/* + * metadata / data + * possibly create / access + * can fail due to: - not present + * - out of space * - * This function verifies that chain (up to the missing link) had not - * changed, fills the missing link and does all housekeeping needed in - * inode (->i_blocks, etc.). In case of success we end up with the full - * chain to new block and return 0. Otherwise (== chain had been changed) - * we free the new blocks (forgetting their buffer_heads, indeed) and - * return -EAGAIN. + * NULL return in the data case is mandatory. */ - -static inline int ext2_splice_branch(struct inode *inode, - long block, - Indirect chain[4], - Indirect *where, - int num) +static struct buffer_head * block_getblk (struct inode * inode, + struct buffer_head * bh, int nr, + int new_block, int * err, int metadata, long *phys, int *new) { - int i; - - /* Verify that place we are splicing to is still there and vacant */ - - /* Writer: pointers, ->i_next_alloc*, ->i_blocks */ - if (!verify_chain(chain, where-1) || *where->p) - /* Writer: end */ - goto changed; - - /* That's it */ - - *where->p = where->key; - inode->u.ext2_i.i_next_alloc_block = block; - inode->u.ext2_i.i_next_alloc_goal = le32_to_cpu(where[num-1].key); - inode->i_blocks += num * inode->i_sb->s_blocksize/512; - - /* Writer: end */ - - /* We are done with atomic stuff, now do the rest of housekeeping */ - - inode->i_ctime = CURRENT_TIME; + int tmp, goal = 0; + u32 * p; + struct buffer_head * result; + int blocksize = inode->i_sb->s_blocksize; - /* had we spliced it onto indirect block? */ - if (where->bh) { - mark_buffer_dirty(where->bh, 1); - if (IS_SYNC(inode) || inode->u.ext2_i.i_osync) { - ll_rw_block (WRITE, 1, &where->bh); - wait_on_buffer(where->bh); + result = NULL; + if (!bh) + goto out; + if (!buffer_uptodate(bh)) { + ll_rw_block (READ, 1, &bh); + wait_on_buffer (bh); + if (!buffer_uptodate(bh)) + goto out; + } + p = (u32 *) bh->b_data + nr; +repeat: + tmp = le32_to_cpu(*p); + if (tmp) { + if (metadata) { + result = getblk (bh->b_dev, tmp, blocksize); + if (tmp == le32_to_cpu(*p)) + goto out; + brelse (result); + goto repeat; + } else { + *phys = tmp; + /* result == NULL */ + goto out; } } - if (IS_SYNC(inode) || inode->u.ext2_i.i_osync) - ext2_sync_inode (inode); - else - mark_inode_dirty(inode); - return 0; - -changed: - for (i = 1; i < num; i++) - bforget(where[i].bh); - for (i = 0; i < num; i++) - ext2_free_blocks(inode, le32_to_cpu(where[i].key), 1); - return -EAGAIN; + if (inode->u.ext2_i.i_next_alloc_block == new_block) + goal = inode->u.ext2_i.i_next_alloc_goal; + if (!goal) { + for (tmp = nr - 1; tmp >= 0; tmp--) { + if (le32_to_cpu(((u32 *) bh->b_data)[tmp])) { + goal = le32_to_cpu(((u32 *)bh->b_data)[tmp]); + break; + } + } + if (!goal) + goal = bh->b_blocknr; + } + tmp = ext2_alloc_block (inode, goal, err); + if (!tmp) + goto out; + if (metadata) { + result = getblk (bh->b_dev, tmp, blocksize); + if (!buffer_uptodate(result)) + wait_on_buffer(result); + memset(result->b_data, 0, inode->i_sb->s_blocksize); + mark_buffer_uptodate(result, 1); + mark_buffer_dirty(result, 1); + if (*p) { + ext2_free_blocks (inode, tmp, 1); + bforget (result); + goto repeat; + } + } else { + if (*p) { + /* + * Nobody is allowed to change block allocation + * state from under us: + */ + ext2_error (inode->i_sb, "block_getblk", + "data block filled under us"); + BUG(); + ext2_free_blocks (inode, tmp, 1); + goto repeat; + } + *phys = tmp; + *new = 1; + } + *p = le32_to_cpu(tmp); + mark_buffer_dirty(bh, 1); + if (IS_SYNC(inode) || inode->u.ext2_i.i_osync) { + ll_rw_block (WRITE, 1, &bh); + wait_on_buffer (bh); + } + inode->i_ctime = CURRENT_TIME; + inode->i_blocks += blocksize/512; + mark_inode_dirty(inode); + inode->u.ext2_i.i_next_alloc_block = new_block; + inode->u.ext2_i.i_next_alloc_goal = tmp; + *err = 0; +out: + brelse (bh); + return result; } -/* - * Allocation strategy is simple: if we have to allocate something, we will - * have to go the whole way to leaf. So let's do it before attaching anything - * to tree, set linkage between the newborn blocks, write them if sync is - * required, recheck the path, free and repeat if check fails, otherwise - * set the last missing link (that will protect us from any truncate-generated - * removals - all blocks on the path are immune now) and possibly force the - * write on the parent block. - * That has a nice additional property: no special recovery from the failed - * allocations is needed - we simply release blocks and do not touch anything - * reachable from inode. - */ - static int ext2_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create) { - int err = -EIO; + int ret, err, new; + struct buffer_head *bh; + unsigned long phys; int offsets[4]; + int *p; Indirect chain[4]; Indirect *partial; - unsigned long goal; - int left; - int depth = ext2_block_to_path(inode, iblock, offsets); + int depth; + depth = ext2_block_to_path(inode, iblock, offsets); if (depth == 0) - goto out; + goto abort; lock_kernel(); -reread: partial = ext2_get_branch(inode, depth, offsets, chain, &err); - /* Simplest case - block found, no allocation needed */ if (!partial) { -got_it: + unlock_kernel(); + for (partial = chain + depth - 1; partial > chain; partial--) + brelse(partial->bh); bh_result->b_dev = inode->i_dev; bh_result->b_blocknr = le32_to_cpu(chain[depth-1].key); bh_result->b_state |= (1UL << BH_Mapped); - /* Clean up and exit */ - partial = chain+depth-1; /* the whole chain */ - goto cleanup; + return 0; } - /* Next simple case - plain lookup or failed read of indirect block */ - if (!create || err == -EIO) { -cleanup: - while (partial > chain) { - brelse(partial->bh); - partial--; - } + while (partial > chain) { + brelse(partial->bh); + partial--; + } + + if (!create) { unlock_kernel(); -out: - return err; + return 0; } + err = -EIO; + new = 0; + ret = 0; + bh = NULL; + /* - * Indirect block might be removed by truncate while we were - * reading it. Handling of that case (forget what we've got and - * reread) is taken out of the main path. + * If this is a sequential block allocation, set the next_alloc_block + * to this block now so that all the indblock and data block + * allocations use the same goal zone */ - if (err == -EAGAIN) - goto changed; - goal = ext2_find_goal(inode, iblock, chain, partial); - if (!goal) - goto changed; + ext2_debug ("block %lu, next %lu, goal %lu.\n", iblock, + inode->u.ext2_i.i_next_alloc_block, + inode->u.ext2_i.i_next_alloc_goal); - left = (chain + depth) - partial; - err = ext2_alloc_branch(inode, left, goal, - offsets+(partial-chain), partial); - if (err) - goto cleanup; - - if (ext2_splice_branch(inode, iblock, chain, partial, left) < 0) - goto changed; + if (iblock == inode->u.ext2_i.i_next_alloc_block + 1) { + inode->u.ext2_i.i_next_alloc_block++; + inode->u.ext2_i.i_next_alloc_goal++; + } - bh_result->b_state |= (1UL << BH_New); - goto got_it; + err = 0; -changed: - while (partial > chain) { - bforget(partial->bh); - partial--; + /* + * ok, these macros clean the logic up a bit and make + * it much more readable: + */ +#define GET_INODE_DATABLOCK(x) \ + inode_getblk(inode, x, iblock, &err, 0, &phys, &new) +#define GET_INODE_PTR(x) \ + inode_getblk(inode, x, iblock, &err, 1, NULL, NULL) +#define GET_INDIRECT_DATABLOCK(x) \ + block_getblk (inode, bh, x, iblock, &err, 0, &phys, &new); +#define GET_INDIRECT_PTR(x) \ + block_getblk (inode, bh, x, iblock, &err, 1, NULL, NULL); + + p = offsets; + if (depth == 1) { + bh = GET_INODE_DATABLOCK(*p); + goto out; } - goto reread; + bh = GET_INODE_PTR(*p); + switch (depth) { + default: /* case 4: */ + bh = GET_INDIRECT_PTR(*++p); + case 3: + bh = GET_INDIRECT_PTR(*++p); + case 2: + bh = GET_INDIRECT_DATABLOCK(*++p); + } + +#undef GET_INODE_DATABLOCK +#undef GET_INODE_PTR +#undef GET_INDIRECT_DATABLOCK +#undef GET_INDIRECT_PTR + +out: + if (bh) + BUG(); // temporary debugging check + if (err) + goto abort; + if (!phys) + BUG(); // must not happen either + + bh_result->b_dev = inode->i_dev; + bh_result->b_blocknr = phys; + bh_result->b_state |= (1UL << BH_Mapped); /* safe */ + if (new) + bh_result->b_state |= (1UL << BH_New); + unlock_kernel(); +abort: + return err; } struct buffer_head * ext2_getblk(struct inode * inode, long block, int create, int * err) diff --git a/include/asm-i386/semaphore.h b/include/asm-i386/semaphore.h index 9088efe2c..972b450cf 100644 --- a/include/asm-i386/semaphore.h +++ b/include/asm-i386/semaphore.h @@ -102,8 +102,8 @@ asmlinkage void __up(struct semaphore * sem); /* * This is ugly, but we want the default case to fall through. - * "down_failed" is a special asm handler that calls the C - * routine that actually waits. See arch/i386/lib/semaphore.S + * "__down_failed" is a special asm handler that calls the C + * routine that actually waits. See arch/i386/kernel/semaphore.c */ extern inline void down(struct semaphore * sem) { diff --git a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h index e39d83dce..a8fd001bc 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack.h +++ b/include/linux/netfilter_ipv4/ip_conntrack.h @@ -31,6 +31,7 @@ enum ip_conntrack_info #include <linux/types.h> #include <linux/skbuff.h> +#include <linux/netfilter_ipv4/ip_conntrack_tcp.h> #ifdef CONFIG_NF_DEBUG #define IP_NF_ASSERT(x) \ @@ -57,7 +58,11 @@ enum ip_conntrack_status { /* Packet seen leaving box: bit 2 set. Can be set, not unset. */ IPS_CONFIRMED_BIT = 2, - IPS_CONFIRMED = (1 << IPS_CONFIRMED_BIT) + IPS_CONFIRMED = (1 << IPS_CONFIRMED_BIT), + + /* Conntrack should never be early-expired. */ + IPS_ASSURED_BIT = 4, + IPS_ASSURED = (1 << IPS_ASSURED_BIT), }; struct ip_conntrack_expect @@ -65,9 +70,11 @@ struct ip_conntrack_expect /* Internal linked list */ struct list_head list; - /* We expect this tuple, but DON'T CARE ABOUT THE SOURCE - per-protocol part. */ - struct ip_conntrack_tuple tuple; + /* We expect this tuple, with the following mask */ + struct ip_conntrack_tuple tuple, mask; + + /* Function to call after setup and insertion */ + int (*expectfn)(struct ip_conntrack *new); /* The conntrack we are part of (set iff we're live) */ struct ip_conntrack *expectant; @@ -116,7 +123,7 @@ struct ip_conntrack /* Storage reserved for other modules: */ union { - int /*enum tcp_conntrack*/ tcp_state; + struct ip_ct_tcp tcp; } proto; union { diff --git a/include/linux/netfilter_ipv4/ip_conntrack_helper.h b/include/linux/netfilter_ipv4/ip_conntrack_helper.h index 006cedef5..728e7bde6 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack_helper.h +++ b/include/linux/netfilter_ipv4/ip_conntrack_helper.h @@ -10,10 +10,10 @@ struct ip_conntrack_helper /* Internal use. */ struct list_head list; - /* Returns TRUE if it wants to help this connection (tuple is - the tuple of REPLY packets from server). */ - int (*will_help)(const struct ip_conntrack_tuple *rtuple); - + /* Mask of things we will help (compared against server response) */ + struct ip_conntrack_tuple tuple; + struct ip_conntrack_tuple mask; + /* Function to call when data passes; return verdict, or -1 to invalidate. */ int (*help)(const struct iphdr *, size_t len, @@ -24,7 +24,11 @@ struct ip_conntrack_helper extern int ip_conntrack_helper_register(struct ip_conntrack_helper *); extern void ip_conntrack_helper_unregister(struct ip_conntrack_helper *); -/* Add an expected connection. */ +/* Add an expected connection: can only have one per connection */ extern int ip_conntrack_expect_related(struct ip_conntrack *related_to, - const struct ip_conntrack_tuple *tuple); + const struct ip_conntrack_tuple *tuple, + const struct ip_conntrack_tuple *mask, + int (*expectfn)(struct ip_conntrack *)); +extern void ip_conntrack_unexpect_related(struct ip_conntrack *related_to); + #endif /*_IP_CONNTRACK_HELPER_H*/ diff --git a/include/linux/netfilter_ipv4/ip_conntrack_tcp.h b/include/linux/netfilter_ipv4/ip_conntrack_tcp.h new file mode 100644 index 000000000..bf466e427 --- /dev/null +++ b/include/linux/netfilter_ipv4/ip_conntrack_tcp.h @@ -0,0 +1,32 @@ +#ifndef _IP_CONNTRACK_TCP_H +#define _IP_CONNTRACK_TCP_H +/* TCP tracking. */ + +#ifndef __KERNEL__ +#error Only in kernel. +#endif + +enum tcp_conntrack { + TCP_CONNTRACK_NONE, + TCP_CONNTRACK_ESTABLISHED, + TCP_CONNTRACK_SYN_SENT, + TCP_CONNTRACK_SYN_RECV, + TCP_CONNTRACK_FIN_WAIT, + TCP_CONNTRACK_TIME_WAIT, + TCP_CONNTRACK_CLOSE, + TCP_CONNTRACK_CLOSE_WAIT, + TCP_CONNTRACK_LAST_ACK, + TCP_CONNTRACK_LISTEN, + TCP_CONNTRACK_MAX +}; + +struct ip_ct_tcp +{ + enum tcp_conntrack state; + + /* Poor man's window tracking: sequence number of valid ACK + handshake completion packet */ + u_int32_t handshake_ack; +}; + +#endif /* _IP_CONNTRACK_TCP_H */ diff --git a/include/linux/netfilter_ipv4/ip_conntrack_tuple.h b/include/linux/netfilter_ipv4/ip_conntrack_tuple.h index 0218e940b..44612efa0 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack_tuple.h +++ b/include/linux/netfilter_ipv4/ip_conntrack_tuple.h @@ -9,7 +9,8 @@ "non-manipulatable" lines, for the benefit of the NAT code. */ -/* The protocol-specific manipulable parts of the tuple. */ +/* The protocol-specific manipulable parts of the tuple: always in + network order! */ union ip_conntrack_manip_proto { /* Add other protocols here. */ @@ -110,6 +111,18 @@ extern inline int ip_ct_tuple_equal(const struct ip_conntrack_tuple *t1, return ip_ct_tuple_src_equal(t1, t2) && ip_ct_tuple_dst_equal(t1, t2); } +extern inline int ip_ct_tuple_mask_cmp(const struct ip_conntrack_tuple *t, + const struct ip_conntrack_tuple *tuple, + const struct ip_conntrack_tuple *mask) +{ + return !(((t->src.ip ^ tuple->src.ip) & mask->src.ip) + || ((t->dst.ip ^ tuple->dst.ip) & mask->dst.ip) + || ((t->src.u.all ^ tuple->src.u.all) & mask->src.u.all) + || ((t->dst.u.all ^ tuple->dst.u.all) & mask->dst.u.all) + || ((t->dst.protonum ^ tuple->dst.protonum) + & mask->dst.protonum)); +} + /* Connections have two entries in the hash table: one for each way */ struct ip_conntrack_tuple_hash { diff --git a/include/linux/netfilter_ipv4/ip_nat_helper.h b/include/linux/netfilter_ipv4/ip_nat_helper.h index 1578d6efc..2171b4325 100644 --- a/include/linux/netfilter_ipv4/ip_nat_helper.h +++ b/include/linux/netfilter_ipv4/ip_nat_helper.h @@ -11,10 +11,10 @@ struct ip_nat_helper /* Internal use */ struct list_head list; - /* Here's the protocol and dst we care about. */ - u_int16_t protocol; - u_int16_t protocol_dst; - + /* Mask of things we will help: vs. tuple from server */ + struct ip_conntrack_tuple tuple; + struct ip_conntrack_tuple mask; + /* Helper function: returns verdict */ unsigned int (*help)(struct ip_conntrack *ct, struct ip_nat_info *info, diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index fb2175942..9f445ec6a 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -446,22 +446,12 @@ #define PCI_DEVICE_ID_X_AGX016 0x0001 #define PCI_VENDOR_ID_MYLEX 0x1069 -#define PCI_DEVICE_ID_MYLEX_DAC960P_V2 0x0001 -#define PCI_DEVICE_ID_MYLEX_DAC960P_V3 0x0002 -#define PCI_DEVICE_ID_MYLEX_DAC960P_V4 0x0010 -#define PCI_DEVICE_ID_MYLEX_DAC960P_V5 0x0020 - -#define PCI_VENDOR_ID_MYLEX 0x1069 -#define PCI_DEVICE_ID_MYLEX_DAC960P_V2 0x0001 -#define PCI_DEVICE_ID_MYLEX_DAC960P_V3 0x0002 -#define PCI_DEVICE_ID_MYLEX_DAC960P_V4 0x0010 -#define PCI_DEVICE_ID_MYLEX_DAC960P_V5 0x0020 - -#define PCI_VENDOR_ID_MYLEX 0x1069 -#define PCI_DEVICE_ID_MYLEX_DAC960P_V2 0x0001 -#define PCI_DEVICE_ID_MYLEX_DAC960P_V3 0x0002 -#define PCI_DEVICE_ID_MYLEX_DAC960P_V4 0x0010 -#define PCI_DEVICE_ID_MYLEX_DAC960P_V5 0x0020 +#define PCI_DEVICE_ID_MYLEX_DAC960_P 0x0001 +#define PCI_DEVICE_ID_MYLEX_DAC960_PD 0x0002 +#define PCI_DEVICE_ID_MYLEX_DAC960_PG 0x0010 +#define PCI_DEVICE_ID_MYLEX_DAC960_LA 0x0020 +#define PCI_DEVICE_ID_MYLEX_DAC960_LP 0x0050 +#define PCI_DEVICE_ID_MYLEX_DAC960_BA 0xBA56 #define PCI_VENDOR_ID_PICOP 0x1066 #define PCI_DEVICE_ID_PICOP_PT86C52X 0x0001 diff --git a/net/core/netfilter.c b/net/core/netfilter.c index f632ef236..f4bb62818 100644 --- a/net/core/netfilter.c +++ b/net/core/netfilter.c @@ -521,6 +521,7 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info, case NF_QUEUE: nf_queue(skb, elem, info->pf, info->hook, info->indev, info->outdev, info->okfn); + break; case NF_DROP: kfree_skb(skb); diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index db276076a..bc892e7db 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile @@ -30,7 +30,7 @@ else endif ifeq ($(CONFIG_IP_NF_FTP),y) -O_OBJS += ip_conntrack_ftp.o +OX_OBJS += ip_conntrack_ftp.o else ifeq ($(CONFIG_IP_NF_FTP),m) MX_OBJS += ip_conntrack_ftp.o @@ -38,7 +38,7 @@ else endif ifeq ($(CONFIG_IP_NF_IPTABLES),y) -O_OBJS += ip_tables.o +OX_OBJS += ip_tables.o else ifeq ($(CONFIG_IP_NF_IPTABLES),m) MX_OBJS += ip_tables.o diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c index 14ebb46e1..da3f97821 100644 --- a/net/ipv4/netfilter/ip_conntrack_core.c +++ b/net/ipv4/netfilter/ip_conntrack_core.c @@ -394,7 +394,7 @@ static inline int unreplied(const struct ip_conntrack_tuple_hash *i) { /* Unconfirmed connections either really fresh or transitory anyway */ - if (!(i->ctrack->status & IPS_SEEN_REPLY) + if (!(i->ctrack->status & IPS_ASSURED) && (i->ctrack->status & IPS_CONFIRMED)) return 1; return 0; @@ -426,17 +426,14 @@ static int early_drop(struct list_head *chain) static inline int helper_cmp(const struct ip_conntrack_helper *i, const struct ip_conntrack_tuple *rtuple) { - return i->will_help(rtuple); + return ip_ct_tuple_mask_cmp(rtuple, &i->tuple, &i->mask); } -/* Compare all but src per-proto part. */ -static int expect_cmp(const struct ip_conntrack_expect *i, - const struct ip_conntrack_tuple *tuple) +/* Compare parts depending on mask. */ +static inline int expect_cmp(const struct ip_conntrack_expect *i, + const struct ip_conntrack_tuple *tuple) { - return (tuple->src.ip == i->tuple.src.ip - && tuple->dst.ip == i->tuple.dst.ip - && tuple->dst.u.all == i->tuple.dst.u.all - && tuple->dst.protonum == i->tuple.dst.protonum); + return ip_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask); } /* Allocate a new conntrack; we set everything up, then grab write @@ -542,6 +539,8 @@ init_conntrack(const struct ip_conntrack_tuple *tuple, /* Update skb to refer to this connection */ skb->nfct = &conntrack->infos[ctinfo]; + if (expected && expected->expectfn) + expected->expectfn(conntrack); return 1; } @@ -722,26 +721,63 @@ int invert_tuplepr(struct ip_conntrack_tuple *inverse, return invert_tuple(inverse, orig, find_proto(orig->dst.protonum)); } +static void unexpect_related(struct ip_conntrack *related_to) +{ + MUST_BE_WRITE_LOCKED(&ip_conntrack_lock); + list_del(&related_to->expected.list); + related_to->expected.expectant = NULL; +} + +/* Would two expected things clash? */ +static inline int expect_clash(const struct ip_conntrack_expect *i, + const struct ip_conntrack_expect *new) +{ + /* Part covered by intersection of masks must be unequal, + otherwise they clash */ + struct ip_conntrack_tuple intersect_mask + = { { i->mask.src.ip & new->mask.src.ip, + { i->mask.src.u.all & new->mask.src.u.all } }, + { i->mask.dst.ip & new->mask.dst.ip, + { i->mask.dst.u.all & new->mask.dst.u.all }, + i->mask.dst.protonum & new->mask.dst.protonum } }; + + return ip_ct_tuple_mask_cmp(&i->tuple, &new->tuple, &intersect_mask); +} + /* Add a related connection. */ int ip_conntrack_expect_related(struct ip_conntrack *related_to, - const struct ip_conntrack_tuple *tuple) + const struct ip_conntrack_tuple *tuple, + const struct ip_conntrack_tuple *mask, + int (*expectfn)(struct ip_conntrack *)) { WRITE_LOCK(&ip_conntrack_lock); + if (related_to->expected.expectant) + unexpect_related(related_to); + related_to->expected.tuple = *tuple; + related_to->expected.mask = *mask; + related_to->expected.expectfn = expectfn; - if (!related_to->expected.expectant) { - list_prepend(&expect_list, &related_to->expected); - related_to->expected.expectant = related_to; - } else { - IP_NF_ASSERT(list_inlist(&expect_list, &related_to->expected)); - IP_NF_ASSERT(related_to->expected.expectant - == related_to); + if (LIST_FIND(&expect_list, expect_clash, + struct ip_conntrack_expect *, &related_to->expected)) { + WRITE_UNLOCK(&ip_conntrack_lock); + return -EBUSY; } + + list_prepend(&expect_list, &related_to->expected); + related_to->expected.expectant = related_to; WRITE_UNLOCK(&ip_conntrack_lock); return 0; } +void ip_conntrack_unexpect_related(struct ip_conntrack *related_to) +{ + WRITE_LOCK(&ip_conntrack_lock); + unexpect_related(related_to); + WRITE_UNLOCK(&ip_conntrack_lock); +} + /* Alter reply tuple (maybe alter helper). If it's already taken, return 0 and don't do alteration. */ int ip_conntrack_alter_reply(struct ip_conntrack *conntrack, diff --git a/net/ipv4/netfilter/ip_conntrack_ftp.c b/net/ipv4/netfilter/ip_conntrack_ftp.c index 2e7547c38..ce0023ec3 100644 --- a/net/ipv4/netfilter/ip_conntrack_ftp.c +++ b/net/ipv4/netfilter/ip_conntrack_ftp.c @@ -121,7 +121,7 @@ static int help(const struct iphdr *iph, size_t len, u_int32_t array[6] = { 0 }; int dir = CTINFO2DIR(ctinfo); unsigned int matchlen, matchoff; - struct ip_conntrack_tuple t; + struct ip_conntrack_tuple t, mask; struct ip_ct_ftp *info = &ct->help.ct_ftp_info; /* Until there's been traffic both ways, don't look in packets. */ @@ -221,22 +221,21 @@ static int help(const struct iphdr *iph, size_t len, | (array[2] << 8) | array[3]), { htons(array[4] << 8 | array[5]) }, IPPROTO_TCP }}); - ip_conntrack_expect_related(ct, &t); + mask = ((struct ip_conntrack_tuple) + { { 0xFFFFFFFF, { 0 } }, + { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }}); + /* Ignore failure; should only happen with NAT */ + ip_conntrack_expect_related(ct, &t, &mask, NULL); UNLOCK_BH(&ip_ftp_lock); return NF_ACCEPT; } -/* Returns TRUE if it wants to help this connection (tuple is the - tuple of REPLY packets from server). */ -static int ftp_will_help(const struct ip_conntrack_tuple *rtuple) -{ - return (rtuple->dst.protonum == IPPROTO_TCP - && rtuple->src.u.tcp.port == __constant_htons(21)); -} - static struct ip_conntrack_helper ftp = { { NULL, NULL }, - ftp_will_help, + { { 0, { __constant_htons(21) } }, + { 0, { 0 }, IPPROTO_TCP } }, + { { 0, { 0xFFFF } }, + { 0, { 0 }, 0xFFFF } }, help }; static int __init init(void) @@ -249,5 +248,8 @@ static void __exit fini(void) ip_conntrack_helper_unregister(&ftp); } +EXPORT_SYMBOL(ip_ftp_lock); +EXPORT_SYMBOL(ip_conntrack_ftp); + module_init(init); module_exit(fini); diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c index f9375d5a5..0aa8426de 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c @@ -17,7 +17,7 @@ #define DEBUGP(format, args...) #endif -/* Protects conntrack->proto.tcp_state */ +/* Protects conntrack->proto.tcp */ static DECLARE_RWLOCK(tcp_lock); /* FIXME: Examine ipfilter's timeouts and conntrack transitions more @@ -27,19 +27,6 @@ static DECLARE_RWLOCK(tcp_lock); from) nor ipfilter do it exactly right. A new conntrack machine taking into account packet loss (which creates uncertainty as to exactly the conntrack of the connection) is required. RSN. --RR */ -enum tcp_conntrack { - TCP_CONNTRACK_NONE, - TCP_CONNTRACK_ESTABLISHED, - TCP_CONNTRACK_SYN_SENT, - TCP_CONNTRACK_SYN_RECV, - TCP_CONNTRACK_FIN_WAIT, - TCP_CONNTRACK_TIME_WAIT, - TCP_CONNTRACK_CLOSE, - TCP_CONNTRACK_CLOSE_WAIT, - TCP_CONNTRACK_LAST_ACK, - TCP_CONNTRACK_LISTEN, - TCP_CONNTRACK_MAX -}; static const char *tcp_conntrack_names[] = { "NONE", @@ -89,19 +76,19 @@ static enum tcp_conntrack tcp_conntracks[2][5][TCP_CONNTRACK_MAX] = { { /* ORIGINAL */ /* sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI */ -/*syn*/ {sSS, sES, sSS, sES, sSS, sSS, sSS, sSS, sSS, sLI }, +/*syn*/ {sSS, sES, sSS, sSR, sSS, sSS, sSS, sSS, sSS, sLI }, /*fin*/ {sTW, sFW, sSS, sTW, sFW, sTW, sCL, sTW, sLA, sLI }, -/*ack*/ {sES, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sES }, +/*ack*/ {sES, sES, sSS, sES, sFW, sTW, sCL, sCW, sLA, sES }, /*rst*/ {sCL, sCL, sSS, sCL, sCL, sTW, sCL, sCL, sCL, sCL }, /*none*/{sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV } }, { /* REPLY */ /* sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI */ -/*syn*/ {sSR, sES, sES, sSR, sSR, sSR, sSR, sSR, sSR, sSR }, +/*syn*/ {sSR, sES, sSR, sSR, sSR, sSR, sSR, sSR, sSR, sSR }, /*fin*/ {sCL, sCW, sSS, sTW, sTW, sTW, sCL, sCW, sLA, sLI }, /*ack*/ {sCL, sES, sSS, sSR, sFW, sTW, sCL, sCW, sCL, sLI }, -/*rst*/ {sCL, sCL, sCL, sSR, sCL, sCL, sCL, sCL, sLA, sLI }, +/*rst*/ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sLA, sLI }, /*none*/{sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV } } }; @@ -141,7 +128,7 @@ static unsigned int tcp_print_conntrack(char *buffer, enum tcp_conntrack state; READ_LOCK(&tcp_lock); - state = conntrack->proto.tcp_state; + state = conntrack->proto.tcp.state; READ_UNLOCK(&tcp_lock); return sprintf(buffer, "%s ", tcp_conntrack_names[state]); @@ -172,7 +159,7 @@ static int tcp_packet(struct ip_conntrack *conntrack, } WRITE_LOCK(&tcp_lock); - oldtcpstate = conntrack->proto.tcp_state; + oldtcpstate = conntrack->proto.tcp.state; newconntrack = tcp_conntracks [CTINFO2DIR(ctinfo)] @@ -182,12 +169,19 @@ static int tcp_packet(struct ip_conntrack *conntrack, if (newconntrack == TCP_CONNTRACK_MAX) { DEBUGP("ip_conntrack_tcp: Invalid dir=%i index=%u conntrack=%u\n", CTINFO2DIR(ctinfo), get_conntrack_index(tcph), - conntrack->proto.tcp_state); + conntrack->proto.tcp.state); WRITE_UNLOCK(&tcp_lock); return -1; } - conntrack->proto.tcp_state = newconntrack; + conntrack->proto.tcp.state = newconntrack; + + /* Poor man's window tracking: record SYN/ACK for handshake check */ + if (oldtcpstate == TCP_CONNTRACK_SYN_SENT + && CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY + && tcph->syn && tcph->ack) + conntrack->proto.tcp.handshake_ack + = htonl(ntohl(tcph->seq) + 1); WRITE_UNLOCK(&tcp_lock); /* If only reply is a RST, we can consider ourselves not to @@ -197,8 +191,16 @@ static int tcp_packet(struct ip_conntrack *conntrack, if (!(conntrack->status & IPS_SEEN_REPLY) && tcph->rst) { if (del_timer(&conntrack->timeout)) conntrack->timeout.function((unsigned long)conntrack); - } else + } else { + /* Set ASSURED if we see see valid ack in ESTABLISHED after SYN_RECV */ + if (oldtcpstate == TCP_CONNTRACK_SYN_RECV + && CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL + && tcph->ack && !tcph->syn + && tcph->ack_seq == conntrack->proto.tcp.handshake_ack) + set_bit(IPS_ASSURED_BIT, &conntrack->status); + ip_ct_refresh(conntrack, tcp_timeouts[newconntrack]); + } return NF_ACCEPT; } @@ -221,8 +223,8 @@ static unsigned long tcp_new(struct ip_conntrack *conntrack, return 0; } - conntrack->proto.tcp_state = newconntrack; - return tcp_timeouts[conntrack->proto.tcp_state]; + conntrack->proto.tcp.state = newconntrack; + return tcp_timeouts[conntrack->proto.tcp.state]; } struct ip_conntrack_protocol ip_conntrack_protocol_tcp diff --git a/net/ipv4/netfilter/ip_conntrack_proto_udp.c b/net/ipv4/netfilter/ip_conntrack_proto_udp.c index 0a65a7a98..644a86a13 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_udp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_udp.c @@ -51,9 +51,11 @@ static int udp_packet(struct ip_conntrack *conntrack, { /* If we've seen traffic both ways, this is some kind of UDP stream. Extend timeout. */ - if (conntrack->status & IPS_SEEN_REPLY) + if (conntrack->status & IPS_SEEN_REPLY) { ip_ct_refresh(conntrack, UDP_STREAM_TIMEOUT); - else + /* Also, more likely to be important, and not a probe */ + set_bit(IPS_ASSURED_BIT, &conntrack->status); + } else ip_ct_refresh(conntrack, UDP_TIMEOUT); return NF_ACCEPT; diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c index 486683bec..20e4aa426 100644 --- a/net/ipv4/netfilter/ip_conntrack_standalone.c +++ b/net/ipv4/netfilter/ip_conntrack_standalone.c @@ -86,19 +86,19 @@ print_conntrack(char *buffer, const struct ip_conntrack *conntrack) len += print_tuple(buffer + len, &conntrack->tuplehash[IP_CT_DIR_REPLY].tuple, proto); -#if 0 + if (conntrack->status & IPS_ASSURED) + len += sprintf(buffer + len, "[ASSURED] "); if (!(conntrack->status & IPS_CONFIRMED)) len += sprintf(buffer + len, "[UNCONFIRMED] "); len += sprintf(buffer + len, "use=%u ", atomic_read(&conntrack->ct_general.use)); -#endif len += sprintf(buffer + len, "\n"); return len; } /* Returns true when finished. */ -static int +static inline int conntrack_iterate(const struct ip_conntrack_tuple_hash *hash, char *buffer, off_t offset, off_t *upto, unsigned int *len, unsigned int maxlen) @@ -169,14 +169,18 @@ static unsigned int ip_confirm(unsigned int hooknum, const struct net_device *out, int (*okfn)(struct sk_buff *)) { - /* We've seen it coming out the other side: confirm (only if - new packet: REJECT can generate TCP RESET response, or ICMP - errors) */ + /* We've seen it coming out the other side: confirm. Beware + REJECT generating TCP RESET response (IP_CT_REPLY), or ICMP + errors (IP_CT_REPLY + IP_CT_RELATED). But new expected + connections must be confirmed as well (eg. ftp data, + IP_CT_RELATED). */ if ((*pskb)->nfct) { struct ip_conntrack *ct = (struct ip_conntrack *)(*pskb)->nfct->master; /* ctinfo is the index of the nfct inside the conntrack */ - if ((*pskb)->nfct - ct->infos == IP_CT_NEW + enum ip_conntrack_info ctinfo = (*pskb)->nfct - ct->infos; + + if ((ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED) && !(ct->status & IPS_CONFIRMED)) ip_conntrack_confirm(ct); } @@ -192,13 +196,7 @@ static unsigned int ip_refrag(unsigned int hooknum, struct rtable *rt = (struct rtable *)(*pskb)->dst; /* We've seen it coming out the other side: confirm */ - if ((*pskb)->nfct) { - struct ip_conntrack *ct - = (struct ip_conntrack *)(*pskb)->nfct->master; - if ((*pskb)->nfct - ct->infos == IP_CT_NEW - && !(ct->status & IPS_CONFIRMED)) - ip_conntrack_confirm(ct); - } + ip_confirm(hooknum, pskb, in, out, okfn); /* Local packets are never produced too large for their interface. We degfragment them at LOCAL_OUT, however, diff --git a/net/ipv4/netfilter/ip_fw_compat.c b/net/ipv4/netfilter/ip_fw_compat.c index 3c8c2e851..6bb1b240c 100644 --- a/net/ipv4/netfilter/ip_fw_compat.c +++ b/net/ipv4/netfilter/ip_fw_compat.c @@ -70,8 +70,10 @@ confirm_connection(struct sk_buff *skb) if (skb->nfct) { struct ip_conntrack *ct = (struct ip_conntrack *)skb->nfct->master; + /* ctinfo is the index of the nfct inside the conntrack */ + enum ip_conntrack_info ctinfo = skb->nfct - ct->infos; - if (skb->nfct - ct->infos == IP_CT_NEW + if ((ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED) && !(ct->status & IPS_CONFIRMED)) ip_conntrack_confirm(ct); } diff --git a/net/ipv4/netfilter/ip_fw_compat_redir.c b/net/ipv4/netfilter/ip_fw_compat_redir.c index d4d910e77..274bb1162 100644 --- a/net/ipv4/netfilter/ip_fw_compat_redir.c +++ b/net/ipv4/netfilter/ip_fw_compat_redir.c @@ -172,7 +172,8 @@ do_redirect(struct sk_buff *skb, struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl); - udph->check = cheat_check(~iph->daddr, newdst, + if (udph->check) /* 0 is a special case meaning no checksum */ + udph->check = cheat_check(~iph->daddr, newdst, cheat_check(udph->dest ^ 0xFFFF, redirpt, udph->check)); diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c index c8bf259b9..0f7b4f8ca 100644 --- a/net/ipv4/netfilter/ip_nat_core.c +++ b/net/ipv4/netfilter/ip_nat_core.c @@ -359,10 +359,14 @@ find_best_ips_proto_fast(struct ip_conntrack_tuple *tuple, if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) tuple->src.ip = mr->range[0].min_ip; else { - tuple->dst.ip = mr->range[0].min_ip; - if (hooknum == NF_IP_LOCAL_OUT - && !do_extra_mangle(tuple->dst.ip, &tuple->src.ip)) + /* Only do extra mangle when required (breaks + socket binding) */ + if (tuple->dst.ip != mr->range[0].min_ip + && hooknum == NF_IP_LOCAL_OUT + && !do_extra_mangle(mr->range[0].min_ip, + &tuple->src.ip)) return NULL; + tuple->dst.ip = mr->range[0].min_ip; } } @@ -456,11 +460,9 @@ get_unique_tuple(struct ip_conntrack_tuple *tuple, static inline int helper_cmp(const struct ip_nat_helper *helper, - u_int16_t protocol, - u_int16_t protocol_dst) + const struct ip_conntrack_tuple *tuple) { - return (protocol == helper->protocol - && protocol_dst == helper->protocol_dst); + return ip_ct_tuple_mask_cmp(tuple, &helper->tuple, &helper->mask); } /* Where to manip the reply packets (will be reverse manip). */ @@ -595,8 +597,7 @@ ip_nat_setup_info(struct ip_conntrack *conntrack, /* If there's a helper, assign it; based on new tuple. */ info->helper = LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *, - new_tuple.dst.protonum, - new_tuple.dst.u.all); + &reply); /* It's done. */ info->initialized |= (1 << HOOK2MANIP(hooknum)); @@ -835,8 +836,7 @@ int ip_nat_helper_register(struct ip_nat_helper *me) int ret = 0; WRITE_LOCK(&ip_nat_lock); - if (LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *, - me->protocol, me->protocol_dst)) + if (LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *,&me->tuple)) ret = -EBUSY; else { list_prepend(&helpers, me); diff --git a/net/ipv4/netfilter/ip_nat_ftp.c b/net/ipv4/netfilter/ip_nat_ftp.c index a0de5a351..d4eb36405 100644 --- a/net/ipv4/netfilter/ip_nat_ftp.c +++ b/net/ipv4/netfilter/ip_nat_ftp.c @@ -72,10 +72,18 @@ ftp_nat_expected(struct sk_buff **pskb, DEBUGP("nat_expected: IP to %u.%u.%u.%u\n", IP_PARTS(newip)); mr.rangesize = 1; - /* We don't want to manip the per-protocol, just the IPs. */ + /* We don't want to manip the per-protocol, just the IPs... */ mr.range[0].flags = IP_NAT_RANGE_MAP_IPS; mr.range[0].min_ip = mr.range[0].max_ip = newip; + /* ... unless we're doing a MANIP_DST, in which case, make + sure we map to the correct port */ + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) { + mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED; + mr.range[0].min = mr.range[0].max + = ((union ip_conntrack_manip_proto) + { htons(ftpinfo->port) }); + } *verdict = ip_nat_setup_info(ct, &mr, hooknum); return 1; @@ -118,7 +126,7 @@ mangle_packet(struct sk_buff **pskb, NIPQUAD((*pskb)->nh.iph->saddr), NIPQUAD((*pskb)->nh.iph->daddr), (*pskb)->nh.iph->protocol); - return NF_DROP; + return 0; } if (newlen > (*pskb)->len + skb_tailroom(*pskb)) { @@ -236,10 +244,16 @@ static int ftp_data_fixup(const struct ip_ct_ftp *ct_ftp_info, struct sk_buff **pskb) { u_int32_t newip; - struct ip_conntrack_tuple t; struct iphdr *iph = (*pskb)->nh.iph; struct tcphdr *tcph = (void *)iph + iph->ihl*4; - + u_int16_t port; + struct ip_conntrack_tuple tuple; + /* Don't care about source port */ + const struct ip_conntrack_tuple mask + = { { 0xFFFFFFFF, { 0 } }, + { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF } }; + + memset(&tuple, 0, sizeof(tuple)); MUST_BE_LOCKED(&ip_ftp_lock); DEBUGP("FTP_NAT: seq %u + %u in %u + %u\n", ct_ftp_info->seq, ct_ftp_info->len, @@ -251,27 +265,35 @@ static int ftp_data_fixup(const struct ip_ct_ftp *ct_ftp_info, /* PASV response: must be where client thinks server is */ newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip; + /* Expect something from client->server */ + tuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip; + tuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip; } else { /* PORT command: must be where server thinks client is */ newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip; + /* Expect something from server->client */ + tuple.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip; + tuple.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip; + } + tuple.dst.protonum = IPPROTO_TCP; + + /* Try to get same port: if not, try to change it. */ + for (port = ct_ftp_info->port; port != 0; port++) { + tuple.dst.u.tcp.port = htons(port); + + if (ip_conntrack_expect_related(ct, &tuple, &mask, NULL) == 0) + break; } + if (port == 0) + return 0; - if (!mangle_packet(pskb, newip, ct_ftp_info->port, + if (!mangle_packet(pskb, newip, port, ct_ftp_info->seq - ntohl(tcph->seq), ct_ftp_info->len, &ftp[ct_ftp_info->ftptype], &ftp[!ct_ftp_info->ftptype])) return 0; - /* Alter conntrack's expectations. */ - - /* We can read expect here without conntrack lock, since it's - only set in ip_conntrack_ftp, with ip_ftp_lock held - writable */ - t = ct->expected.tuple; - t.dst.ip = newip; - ip_conntrack_expect_related(ct, &t); - return 1; } @@ -368,8 +390,12 @@ static unsigned int help(struct ip_conntrack *ct, return NF_ACCEPT; } -static struct ip_nat_helper ftp -= { { NULL, NULL }, IPPROTO_TCP, __constant_htons(21), help, "ftp" }; +static struct ip_nat_helper ftp = { { NULL, NULL }, + { { 0, { __constant_htons(21) } }, + { 0, { 0 }, IPPROTO_TCP } }, + { { 0, { 0xFFFF } }, + { 0, { 0 }, 0xFFFF } }, + help, "ftp" }; static struct ip_nat_expect ftp_expect = { { NULL, NULL }, ftp_nat_expected }; diff --git a/net/ipv4/netfilter/ip_nat_proto_udp.c b/net/ipv4/netfilter/ip_nat_proto_udp.c index e0dc25910..622aee05a 100644 --- a/net/ipv4/netfilter/ip_nat_proto_udp.c +++ b/net/ipv4/netfilter/ip_nat_proto_udp.c @@ -90,7 +90,8 @@ udp_manip_pkt(struct iphdr *iph, size_t len, oldip = iph->daddr; portptr = &hdr->dest; } - hdr->check = ip_nat_cheat_check(~oldip, manip->ip, + if (hdr->check) /* 0 is a special case meaning no checksum */ + hdr->check = ip_nat_cheat_check(~oldip, manip->ip, ip_nat_cheat_check(*portptr ^ 0xFFFF, manip->u.udp.port, hdr->check)); diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index 39574b7d4..2ac8b22e2 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c @@ -199,38 +199,36 @@ static void ipq_destroy_queue(ipq_queue_t *q) static int ipq_mangle_ipv4(ipq_verdict_msg_t *v, ipq_queue_element_t *e) { + int diff; struct iphdr *user_iph = (struct iphdr *)v->payload; if (v->data_len < sizeof(*user_iph)) return 0; - if (e->skb->nh.iph->check != user_iph->check) { - int diff = v->data_len - e->skb->len; - - if (diff < 0) - skb_trim(e->skb, v->data_len); - else if (diff > 0) { - if (v->data_len > 0xFFFF) - return -EINVAL; - if (diff > skb_tailroom(e->skb)) { - struct sk_buff *newskb; - - newskb = skb_copy_expand(e->skb, - skb_headroom(e->skb), - diff, - GFP_ATOMIC); - if (newskb == NULL) { - printk(KERN_WARNING "ip_queue: OOM " - "in mangle, dropping packet\n"); - return -ENOMEM; - } - kfree_skb(e->skb); - e->skb = newskb; + diff = v->data_len - e->skb->len; + if (diff < 0) + skb_trim(e->skb, v->data_len); + else if (diff > 0) { + if (v->data_len > 0xFFFF) + return -EINVAL; + if (diff > skb_tailroom(e->skb)) { + struct sk_buff *newskb; + + newskb = skb_copy_expand(e->skb, + skb_headroom(e->skb), + diff, + GFP_ATOMIC); + if (newskb == NULL) { + printk(KERN_WARNING "ip_queue: OOM " + "in mangle, dropping packet\n"); + return -ENOMEM; } - skb_put(e->skb, diff); + kfree_skb(e->skb); + e->skb = newskb; } - memcpy(e->skb->data, v->payload, v->data_len); - e->skb->nfcache |= NFC_ALTERED; + skb_put(e->skb, diff); } + memcpy(e->skb->data, v->payload, v->data_len); + e->skb->nfcache |= NFC_ALTERED; return 0; } diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 40b19760b..7a24b21dd 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -1748,5 +1748,11 @@ static void __exit fini(void) #endif } +EXPORT_SYMBOL(ipt_register_table); +EXPORT_SYMBOL(ipt_unregister_table); +EXPORT_SYMBOL(ipt_register_match); +EXPORT_SYMBOL(ipt_unregister_match); +EXPORT_SYMBOL(ipt_do_table); + module_init(init); module_exit(fini); |