diff -u --recursive --new-file v1.1.14/linux/Makefile linux/Makefile --- v1.1.14/linux/Makefile Tue May 24 08:47:06 1994 +++ linux/Makefile Tue May 24 09:45:54 1994 @@ -1,6 +1,6 @@ VERSION = 1 PATCHLEVEL = 1 -SUBLEVEL = 14 +SUBLEVEL = 15 all: Version zImage diff -u --recursive --new-file v1.1.14/linux/config.in linux/config.in --- v1.1.14/linux/config.in Tue May 24 08:47:06 1994 +++ linux/config.in Wed May 25 15:48:07 1994 @@ -50,13 +50,16 @@ bool 'Adaptec AHA152X support' CONFIG_SCSI_AHA152X n bool 'Adaptec AHA1542 support' CONFIG_SCSI_AHA1542 y bool 'Adaptec AHA1740 support' CONFIG_SCSI_AHA1740 n +bool 'BusLogic SCSI support' CONFIG_SCSI_BUSLOGIC n bool 'Future Domain 16xx SCSI support' CONFIG_SCSI_FUTURE_DOMAIN n bool 'Generic NCR5380 SCSI support' CONFIG_SCSI_GENERIC_NCR5380 n +#bool 'Always IN2000 SCSI support' CONFIG_SCSI_IN2000 n bool 'PAS16 SCSI support' CONFIG_SCSI_PAS16 n bool 'Seagate ST-02 and Future Domain TMC-8xx SCSI support' CONFIG_SCSI_SEAGATE n bool 'Trantor T128/T128F/T228 SCSI support' CONFIG_SCSI_T128 n bool 'UltraStor SCSI support' CONFIG_SCSI_ULTRASTOR n bool '7000FASST SCSI support' CONFIG_SCSI_7000FASST n +#bool 'SCSI debugging host adapter' CONFIG_SCSI_DEBUG n fi diff -u --recursive --new-file v1.1.14/linux/drivers/scsi/ChangeLog linux/drivers/scsi/ChangeLog --- v1.1.14/linux/drivers/scsi/ChangeLog Thu Jan 1 02:00:00 1970 +++ linux/drivers/scsi/ChangeLog Tue May 24 09:19:21 1994 @@ -0,0 +1,645 @@ +Sun May 15 20:24:34 1994 Eric Youngdale (eric@esp22) + + Post-codefreeze thaw... + + * buslogic.[c,h]: New driver from David Gentzel. + + * hosts.h: Add use_clustering field to explicitly say whether + clustering should be used for devices attached to this host + adapter. The buslogic board apparently supports large SG lists, + but it is apparently faster if sd.c condenses this into a smaller + list. + + * sd.c: Use this field instead of heuristic. + + * All host adapter include files: Add appropriate initializer for + use_clustering field. + + * scsi.h: Add #defines for return codes for the abort and reset + functions. There are now a specific set of return codes to fully + specify all of the possible things that the low-level adapter + could do. + + * scsi.c: Act based upon return codes from abort/reset functions. + + * All host adapter abort/reset functions: Return new return code. + + * Add code in scsi.c to help debug timeouts. Use #define + DEBUG_TIMEOUT to enable this. + + * scsi.c: If the host->irq field is set, use + disable_irq/enable_irq before calling queuecommand if we + are not already in an interrupt. Reduce races, and we + can be sloppier about cli/sti in the interrupt routines now + (reduce interrupt latency). + + * constants.c: Fix some things to eliminate warnings. Add some + sense descriptions that were omitted before. + + * aha1542.c: Watch for SCRD from host adapter - if we see it, set + a flag. Currently we only print out the number of pending + commands that might need to be restarted. + + * aha1542.c (aha1542_abort): Look for lost interrupts, OGMB still + full, and attempt to recover. Otherwise give up. + + * aha1542.c (aha1542_reset): Try BUS DEVICE RESET, and then pass + DID_RESET back up to the upper level code for all commands running + on this target (even on different LUNs). + +Sat May 7 14:54:01 1994 + + * Linux 1.1.12 released. + + * st.c, st.h: New version from Kai. Supports boot time + specification of number of buffers. + + * wd7000.[c,h]: Updated driver from John Boyd. Now supports + more than one wd7000 board in machine at one time, among other things. + +Wed Apr 20 22:20:35 1994 + + * Linux 1.1.8 released. + + * sd.c: Add a few type casts where scsi_malloc is called. + +Wed Apr 13 12:53:29 1994 + + * Linux 1.1.4 released. + + * scsi.c: Clean up a few printks (use %p to print pointers). + +Wed Apr 13 11:33:02 1994 + + * Linux 1.1.3 released. + + * fdomain.c: Update to version 5.16 (Handle different FIFO sizes + better). + +Fri Apr 8 08:57:19 1994 + + * Linux 1.1.2 released. + + * Throughout: SCSI portion of cluster diffs added. + +Tue Apr 5 07:41:50 1994 + + * Linux 1.1 development tree initiated. + + * The linux 1.0 development tree is now effectively frozen except + for obvious bugfixes. + +****************************************************************** +****************************************************************** +****************************************************************** +****************************************************************** + +Sun Apr 17 00:17:39 1994 + + * Linux 1.0, patchlevel 9 released. + + * fdomain.c: Update to version 5.16 (Handle different FIFO sizes + better). + +Thu Apr 7 08:36:20 1994 + + * Linux 1.0, patchlevel8 released. + + * fdomain.c: Update to version 5.15 from 5.9. Handles 3.4 bios. + +Sun Apr 3 14:43:03 1994 + + * Linux 1.0, patchlevel6 released. + + * wd7000.c: Make stab at fixing race condition. + +Sat Mar 26 14:14:50 1994 + + * Linux 1.0, patchlevel5 released. + + * aha152x.c, Makefile: Fix a few bugs (too much data message). + Add a few more bios signatures. (Patches from Juergen). + + * aha1542.c: Fix race condition in aha1542_out. + +Mon Mar 21 16:36:20 1994 + + * Linux 1.0, patchlevel3 released. + + * sd.c, st.c, sr.c, sg.c: Return -ENXIO, not -ENODEV if we attempt + to open a non-existant device. + + * scsi.c: Add Chinon cdrom to blacklist. + + * sr_ioctl.c: Check return status of verify_area. + +Sat Mar 6 16:06:19 1994 + + * Linux 1.0 released (technically a pre-release). + + * scsi.c: Add IMS CDD521, Maxtor XT-8760S to blacklist. + +Tue Feb 15 10:58:20 1994 + + * pl15e released. + + * aha1542.c: For 1542C, allow dynamic device scan with >1Gb turned + off. + + * constants.c: Fix typo in definition of CONSTANTS. + + * pl15d released. + +Fri Feb 11 10:10:16 1994 + + * pl15c released. + + * scsi.c: Add Maxtor XT-3280 and Rodime RO3000S to blacklist. + + * scsi.c: Allow tagged queueing for scsi 3 devices as well. + Some really old devices report a version number of 0. Disallow + LUN != 0 for these. + +Thu Feb 10 09:48:57 1994 + + * pl15b released. + +Sun Feb 6 12:19:46 1994 + + * pl15a released. + +Fri Feb 4 09:02:17 1994 + + * scsi.c: Add Teac cdrom to blacklist. + +Thu Feb 3 14:16:43 1994 + + * pl15 released. + +Tue Feb 1 15:47:43 1994 + + * pl14w released. + + * wd7000.c (wd_bases): Fix typo in last change. + +Mon Jan 24 17:37:23 1994 + + * pl14u released. + + * aha1542.c: Support 1542CF/extended bios. Different from 1542C + + * wd7000.c: Allow bios at 0xd8000 as well. + + * ultrastor.c: Do not truncate cylinders to 1024. + + * fdomain.c: Update to version 5.9 (add new bios signature). + + * NCR5380.c: Update from Drew - should work a lot better now. + +Sat Jan 8 15:13:10 1994 + + * pl14o released. + + * sr_ioctl.c: Zero reserved field before trying to set audio volume. + +Wed Jan 5 13:21:10 1994 + + * pl14m released. + + * fdomain.c: Update to version 5.8. No functional difference??? + +Tue Jan 4 14:26:13 1994 + + * pl14l released. + + * ultrastor.c: Remove outl, inl functions (now provided elsewhere). + +Mon Jan 3 12:27:25 1994 + + * pl14k released. + + * aha152x.c: Remove insw and outsw functions. + + * fdomain.c: Ditto. + +Wed Dec 29 09:47:20 1993 + + * pl14i released. + + * scsi.c: Support RECOVERED_ERROR for tape drives. + + * st.c: Update of tape driver from Kai. + +Tue Dec 21 09:18:30 1993 + + * pl14g released. + + * aha1542.[c,h]: Support extended BIOS stuff. + + * scsi.c: Clean up messages about disks, so they are displayed as + sda, sdb, etc instead of sd0, sd1, etc. + + * sr.c: Force reread of capacity if disk was changed. + Clear buffer before asking for capacity/sectorsize (some drives + do not report this properly). Set needs_sector_size flag if + drive did not return sensible sector size. + +Mon Dec 13 12:13:47 1993 + + * aha152x.c: Update to version .101 from Juergen. + +Mon Nov 29 03:03:00 1993 + + * linux 0.99.14 released. + + * All scsi stuff moved from kernel/blk_drv/scsi to drivers/scsi. + + * Throughout: Grammatical corrections to various comments. + + * Makefile: fix so that we do not need to compile things we are + not going to use. + + * NCR5380.c, NCR5380.h, g_NCR5380.c, g_NCR5380.h, pas16.c, + pas16.h, t128.c, t128.h: New files from Drew. + + * aha152x.c, aha152x.h: New files from Juergen Fischer. + + * aha1542.c: Support for more than one 1542 in the machine + at the same time. Make functions static that do not need + visibility. + + * aha1740.c: Set NEEDS_JUMPSTART flag in reset function, so we + know to restart the command. Change prototype of aha1740_reset + to take a command pointer. + + * constants.c: Clean up a few things. + + * fdomain.c: Update to version 5.6. Move snarf_region. Allow + board to be set at different SCSI ids. Remove support for + reselection (did not work well). Set JUMPSTART flag in reset + code. + + * hosts.c: Support new low-level adapters. Allow for more than + one adapter of a given type. + + * hosts.h: Allow for more than one adapter of a given type. + + * scsi.c: Add scsi_device_types array, if NEEDS_JUMPSTART is set + after a low-level reset, start the command again. Sort blacklist, + and add Maxtor MXT-1240S, XT-4170S, NEC CDROM 84, Seagate ST157N. + + * scsi.h: Add constants for tagged queueing. + + * Throughout: Use constants from major.h instead of hardcoded + numbers for major numbers. + + * scsi_ioctl.c: Fix bug in buffer length in ioctl_command. Use + verify_area in GET_IDLUN ioctl. Add new ioctls for + TAGGED_QUEUE_ENABLE, DISABLE. Only allow IOCTL_SEND_COMMAND by + superuser. + + * sd.c: Only pay attention to UNIT_ATTENTION for removable disks. + Fix bug where sometimes portions of blocks would get lost + resulting in processes hanging. Add messages when we spin up a + disk, and fix a bug in the timing. Increase read-ahead for disks + that are on a scatter-gather capable host adapter. + + * seagate.c: Fix so that some parameters can be set from the lilo + prompt. Supply jumpstart flag if we are resetting and need the + command restarted. Fix so that we return 1 if we detect a card + so that multiple card detection works correctly. Add yet another + signature for FD cards (950). Add another signature for ST0x. + + * sg.c, sg.h: New files from Lawrence Foard for generic scsi + access. + + * sr.c: Add type casts for (void*) so that we can do pointer + arithmetic. Works with GCC without this, but it is not strictly + correct. Same bugfix as was in sd.c. Increase read-ahead a la + disk driver. + + * sr_ioctl.c: Use scsi_malloc buffer instead of buffer from stack + since we cannot guarantee that the stack is < 16Mb. + + ultrastor.c: Update to support 24f properly (JFC's driver). + + wd7000.c: Supply jumpstart flag for reset. Do not round up + number of cylinders in biosparam function. + +Sat Sep 4 20:49:56 1993 + + * 0.99pl13 released. + + * Throughout: Use check_region/snarf_region for all low-level + drivers. + + * aha1542.c: Do hard reset instead of soft (some ethercard probes + screw us up). + + * scsi.c: Add new flag ASKED_FOR_SENSE so that we can tell if we are + in a loop whereby the device returns null sense data. + + * sd.c: Add code to spin up a drive if it is not already spinning. + Do this one at a time to make it easier on power supplies. + + * sd_ioctl.c: Use sync_dev instead of fsync_dev in BLKFLSBUF ioctl. + + * seagate.c: Switch around DATA/CONTROL lines. + + * st.c: Change sense to unsigned. + +Thu Aug 5 11:59:18 1993 + + * 0.99pl12 released. + + * constants.c, constants.h: New files with ascii descriptions of + various conditions. + + * Makefile: Do not try and count the number of low-level drivers, + just generate the list of .o files. + + * aha1542.c: Replace 16 with sizeof(SCpnt->sense_buffer). Add tests + for addresses > 16Mb, panic if we find one. + + * aha1740.c: Ditto with sizeof(). + + * fdomain.c: Update to version 3.18. Add new signature, register IRQ + with irqaction. Use ID 7 for new board. Be more intelligent about + obtaining the h/s/c numbers for biosparam. + + * hosts.c: Do not depend upon Makefile generated count of the number + of low-level host adapters. + + * scsi.c: Use array for scsi_command_size instead of a function. Add + Texel cdrom and Maxtor XT-4380S to blacklist. Allow compile time + option for no-multi lun scan. Add semaphore for possible problems + with handshaking, assume device is faulty until we know it not to be + the case. Add DEBUG_INIT symbol to dump info as we scan for devices. + Zero sense buffer so we can tell if we need to request it. When + examining sense information, request sense if buffer is all zero. + If RESET, request sense information to see what to do next. + + * scsi_debug.c: Change some constants to use symbols like INT_MAX. + + * scsi_ioctl.c (kernel_scsi_ioctl): New function -for making ioctl + calls from kernel space. + + * sd.c: Increase timeout to 300. Use functions in constants.h to + display info. Use scsi_malloc buffer for READ_CAPACITY, since + we cannot guarantee that a stack based buffer is < 16Mb. + + * sd_ioctl.c: Add BLKFLSBUF ioctl. + + * seagate.c: Add new compile time options for ARBITRATE, + SLOW_HANDSHAKE, and SLOW_RATE. Update assembly loops for transferring + data. Use kernel_scsi_ioctl to request mode page with geometry. + + * sr.c: Use functions in constants.c to display messages. + + * st.c: Support for variable block size. + + * ultrastor.c: Do not use cache for tape drives. Set + unchecked_isa_dma flag, even though this may not be needed (gets set + later). + +Sat Jul 17 18:32:44 1993 + + * 0.99pl11 released. C++ compilable. + + * Throughout: Add type casts all over the place, and use "ip" instead + of "info" in the various biosparam functions. + + * Makefile: Compile seagate.c with C++ compiler. + + * aha1542.c: Always set ccb pointer as this gets trashed somehow on + some systems. Add a few type casts. Update biosparam function a little. + + * aha1740.c: Add a few type casts. + + * fdomain.c: Update to version 3.17 from 3.6. Now works with + TMC-18C50. + + * scsi.c: Minor changes here and there with datatypes. Save use_sg + when requesting sense information so that this can properly be + restored if we retry the command. Set aside dma buffers assuming each + block is 1 page, not 1Kb minix block. + + * scsi_ioctl.c: Add a few type casts. Other minor changes. + + * sd.c: Correctly free all scsi_malloc'd memory if we run out of + dma_pool. Store blocksize information for each partition. + + * seagate.c: Minor cleanups here and there. + + * sr.c: Set up blocksize array for all discs. Fix bug in freeing + buffers if we run out of dma pool. + +Thu Jun 2 17:58:11 1993 + + * 0.99pl10 released. + + * aha1542.c: Support for BT 445S (VL-bus board with no dma channel). + + * fdomain.c: Upgrade to version 3.6. Preliminary support for TNC-18C50. + + * scsi.c: First attempt to fix problem with old_use_sg. Change + NOT_READY to a SUGGEST_ABORT. Fix timeout race where time might + get decremented past zero. + + * sd.c: Add block_fsync function to dispatch table. + + * sr.c: Increase timeout to 500 from 250. Add entry for sync in + dispatch table (supply NULL). If we do not have a sectorsize, + try and get it in the sd_open function. Add new function just to + obtain sectorsize. + + * sr.h: Add needs_sector_size semaphore. + + * st.c: Add NULL for fsync in dispatch table. + + * wd7000.c: Allow another condition for power on that are normal + and do not require a panic. + +Thu Apr 22 23:10:11 1993 + + * 0.99pl9 released. + + * aha1542.c: Use (void) instead of () in setup_mailboxes. + + * scsi.c: Initialize transfersize and underflow fields in SCmd to 0. + Do not panic for unsupported message bytes. + + * scsi.h: Allocate 12 bytes instead of 10 for commands. Add + transfersize and underflow fields. + + * scsi_ioctl.c: Further bugfix to ioctl_probe. + + * sd.c: Use long instead of int for last parameter in sd_ioctl. + Initialize transfersize and underflow fields. + + * sd_ioctl.c: Ditto for sd_ioctl(,,,,); + + * seagate.c: New version from Drew. Includes new signatures for FD + cards. Support for 0ws jumper. Correctly initialize + scsi_hosts[hostnum].this_id. Improved handing of + disconnect/reconnect, and support command linking. Use + transfersize and underflow fields. Support scatter-gather. + + * sr.c, sr_ioctl.c: Use long instead of int for last parameter in sr_ioctl. + Use buffer and buflength in do_ioctl. Patches from Chris Newbold for + scsi-2 audio commands. + + * ultrastor.c: Comment out in_byte (compiler warning). + + * wd7000.c: Change () to (void) in wd7000_enable_dma. + +Wed Mar 31 16:36:25 1993 + + * 0.99pl8 released. + + * aha1542.c: Handle mailboxes better for 1542C. + Do not truncate number of cylinders at 1024 for biosparam call. + + * aha1740.c: Fix a few minor bugs for multiple devices. + Same as above for biosparam. + + * scsi.c: Add lockable semaphore for removable devices that can have + media removal prevented. Add another signature for flopticals. + (allocate_device): Fix race condition. Allow more space in dma pool + for blocksizes of up to 4Kb. + + * scsi.h: Define COMMAND_SIZE. Define a SCSI specific version of + INIT_REQUEST that can run with interrupts off. + + * scsi_ioctl.c: Make ioctl_probe function more idiot-proof. If + a removable device says ILLEGAL REQUEST to a door-locking command, + clear lockable flag. Add SCSI_IOCTL_GET_IDLUN ioctl. Do not attempt + to lock door for devices that do not have lockable semaphore set. + + * sd.c: Fix race condition for multiple disks. Use INIT_SCSI_REQUEST + instead of INIT_REQUEST. Allow sector sizes of 1024 and 256. For + removable disks that are not ready, mark them as having a media change + (some drives do not report this later). + + * seagate.c: Use volatile keyword for memory-mapped register pointers. + + * sr.c: Fix race condition, a la sd.c. Increase the number of retries + to 1. Use INIT_SCSI_REQUEST. Allow 512 byte sector sizes. Do a + read_capacity when we init the device so we know the size and + sectorsize. + + * st.c: If ioctl not found in st.c, try scsi_ioctl for others. + + * ultrastor.c: Do not truncate number of cylinders at 1024 for + biosparam call. + + * wd7000.c: Ditto. + Throughout: Use COMMAND_SIZE macro to determine length of scsi + command. + + + +Sat Mar 13 17:31:29 1993 + + * 0.99pl7 released. + + Throughout: Improve punctuation in some messages, and use new + verify_area syntax. + + * aha1542.c: Handle unexpected interrupts better. + + * scsi.c: Ditto. Handle reset conditions a bit better, asking for + sense information and retrying if required. + + * scsi_ioctl.c: Allow for 12 byte scsi commands. + + * ultrastor.c: Update to use scatter-gather. + +Sat Feb 20 17:57:15 1993 + + * 0.99pl6 released. + + * fdomain.c: Update to version 3.5. Handle spurious interrupts + better. + + * sd.c: Use register_blkdev function. + + * sr.c: Ditto. + + * st.c: Use register_chrdev function. + + * wd7000.c: Undo previous change. + +Sat Feb 6 11:20:43 1993 + + * 0.99pl5 released. + + * scsi.c: Fix bug in testing for UNIT_ATTENTION. + + * wd7000.c: Check at more addresses for bios. Fix bug in biosparam + (heads & sectors turned around). + +Wed Jan 20 18:13:59 1993 + + * 0.99pl4 released. + + * scsi.c: Ignore leading spaces when looking for blacklisted devices. + + * seagate.c: Add a few new signatures for FD cards. Another patch + with SCint to fix race condition. Use recursion_depth to keep track + of how many times we have been recursively called, and do not start + another command unless we are on the outer level. Fixes bug + with Syquest cartridge drives (used to crash kernel), because + they do not disconnect with large data transfers. + +Tue Jan 12 14:33:36 1993 + + * 0.99pl3 released. + + * fdomain.c: Update to version 3.3 (a few new signatures). + + * scsi.c: Add CDU-541, Denon DRD-25X to blacklist. + (allocate_request, request_queueable): Init request.waiting to NULL if + non-buffer type of request. + + * seagate.c: Allow controller to be overridden with CONTROLLER symbol. + Set SCint=NULL when we are done, to remove race condition. + + * st.c: Changes from Kai. + +Wed Dec 30 20:03:47 1992 + + * 0.99pl2 released. + + * scsi.c: Blacklist back in. Remove Newbury drive as other bugfix + eliminates need for it here. + + * sd.c: Return ENODEV instead of EACCES if no such device available. + (sd_init) Init blkdev_fops earlier so that sd_open is available sooner. + + * sr.c: Same as above for sd.c. + + * st.c: Return ENODEV instead of ENXIO if no device. Init chrdev_fops + sooner, so that it is always there even if no tapes. + + * seagate.c (controller_type): New variable to keep track of ST0x or + FD. Modify signatures list to indicate controller type, and init + controller_type once we find a match. + + * wd7000.c (wd7000_set_sync): Remove redundant function. + +Sun Dec 20 16:26:24 1992 + + * 0.99pl1 released. + + * scsi_ioctl.c: Bugfix - check dev->index, not dev->id against + NR_SCSI_DEVICES. + + * sr_ioctl.c: Verify that device exists before allowing an ioctl. + + * st.c: Patches from Kai - change timeout values, improve end of tape + handling. + +Sun Dec 13 18:15:23 1992 + + * 0.99 kernel released. Baseline for this ChangeLog. diff -u --recursive --new-file v1.1.14/linux/drivers/scsi/Makefile linux/drivers/scsi/Makefile --- v1.1.14/linux/drivers/scsi/Makefile Sat Mar 26 15:08:15 1994 +++ linux/drivers/scsi/Makefile Tue May 24 09:19:22 1994 @@ -11,6 +11,14 @@ AHA152X = -DDEBUG_AHA152X -DAUTOCONF +ifeq (${CFLAGS},) +CFLAGS = -D__KERNEL__=1 \ + -Wall -Wstrict-prototypes -I. -I../../include \ + -O2 -fomit-frame-pointer -m486 + +include ../../.config +endif + SCSI_OBJS = SCSI_SRCS = @@ -54,6 +62,11 @@ SCSI_SRCS := $(SCSI_SRCS) aha1740.c endif +ifdef CONFIG_SCSI_BUSLOGIC +SCSI_OBJS := $(SCSI_OBJS) buslogic.o +SCSI_SRCS := $(SCSI_SRCS) buslogic.c +endif + ifdef CONFIG_SCSI_DEBUG SCSI_OBJS := $(SCSI_OBJS) scsi_debug.o SCSI_SRCS := $(SCSI_SRCS) scsi_debug.c @@ -62,6 +75,11 @@ ifdef CONFIG_SCSI_FUTURE_DOMAIN SCSI_OBJS := $(SCSI_OBJS) fdomain.o SCSI_SRCS := $(SCSI_SRCS) fdomain.c +endif + +ifdef CONFIG_SCSI_IN2000 +SCSI_OBJS := $(SCSI_OBJS) in2000.o +SCSI_SRCS := $(SCSI_SRCS) in2000.c endif ifdef CONFIG_SCSI_GENERIC_NCR5380 diff -u --recursive --new-file v1.1.14/linux/drivers/scsi/NCR5380.c linux/drivers/scsi/NCR5380.c --- v1.1.14/linux/drivers/scsi/NCR5380.c Mon Jan 24 14:19:19 1994 +++ linux/drivers/scsi/NCR5380.c Tue May 24 09:19:22 1994 @@ -2266,7 +2266,7 @@ #endif /* def REAL_DMA */ /* - * Function : int NCR5380_abort (Scsi_Cmnd *cmd, int code) + * Function : int NCR5380_abort (Scsi_Cmnd *cmd) * * Purpose : abort a command * @@ -2285,7 +2285,7 @@ #ifndef NCR5380_abort static #endif -int NCR5380_abort (Scsi_Cmnd *cmd, int code) { +int NCR5380_abort (Scsi_Cmnd *cmd) { NCR5380_local_declare(); struct Scsi_Host *instance = cmd->host; struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) @@ -2313,14 +2313,14 @@ if (cmd == tmp) { (*prev) = (Scsi_Cmnd *) tmp->host_scribble; tmp->host_scribble = NULL; - tmp->result = (code ? code : DID_ABORT) << 16; + tmp->result = DID_ABORT << 16; sti(); #if (NDEBUG & NDEBUG_ABORT) printk("scsi%d : abort removed command from issue queue.\n", instance->host_no); #endif tmp->done(tmp); - return 0; + return SCSI_ABORT_SUCCESS; } /* @@ -2339,7 +2339,7 @@ #if (NDEBUG & NDEBUG_ABORT) printk("scsi%d : abort failed, command connected.\n", instance->host_no); #endif - return -1; + return SCSI_ABORT_NOT_RUNNING; } /* @@ -2376,7 +2376,7 @@ #endif if (NCR5380_select (instance, cmd, (int) cmd->tag)) - return 1; + return SCSI_ABORT_BUSY; #if (NDEBUG & NDEBUG_ABORT) printk("scsi%d : nexus restablished.\n", instance->host_no); @@ -2397,10 +2397,10 @@ if (cmd == tmp) { *prev = (Scsi_Cmnd *) tmp->host_scribble; tmp->host_scribble = NULL; - tmp->result = (code ? code : DID_ABORT) << 16; + tmp->result = DID_ABORT << 16; sti(); tmp->done(tmp); - return 0; + return SCSI_ABORT_SUCCESS; } } @@ -2417,7 +2417,7 @@ sti(); printk("scsi%d : warning : SCSI command probably completed successfully\n" " before abortion\n", instance->host_no); - return 0; + return SCSI_ABORT_NOT_RUNNING; } diff -u --recursive --new-file v1.1.14/linux/drivers/scsi/NCR5380.h linux/drivers/scsi/NCR5380.h --- v1.1.14/linux/drivers/scsi/NCR5380.h Mon Jan 24 14:19:57 1994 +++ linux/drivers/scsi/NCR5380.h Tue May 24 09:19:18 1994 @@ -249,7 +249,7 @@ #ifndef NCR5380_abort static #endif -int NCR5380_abort (Scsi_Cmnd *cmd, int code); +int NCR5380_abort (Scsi_Cmnd *cmd); #ifndef NCR5380_reset static #endif diff -u --recursive --new-file v1.1.14/linux/drivers/scsi/aha152x.c linux/drivers/scsi/aha152x.c --- v1.1.14/linux/drivers/scsi/aha152x.c Sat Mar 26 15:08:16 1994 +++ linux/drivers/scsi/aha152x.c Tue May 24 09:19:18 1994 @@ -155,7 +155,7 @@ Drew Eckhardt (drew@cs.colorado.edu) - Eric Youngdale (eric@tantalus.nrl.navy.mil) + Eric Youngdale (ericy@cais.com) special thanks to Eric Youngdale for the free(!) supplying the documentation on the chip. @@ -781,7 +781,7 @@ * Abort a queued command * (commands that are on the bus can't be aborted easily) */ -int aha152x_abort( Scsi_Cmnd *SCpnt, int code ) +int aha152x_abort( Scsi_Cmnd *SCpnt) { Scsi_Cmnd *ptr, *prev; @@ -809,16 +809,16 @@ sti(); ptr->host_scribble = NULL; - ptr->result = (code ? code : DID_ABORT ) << 16; + ptr->result = DID_ABORT << 16; ptr->done(ptr); - return 0; + return SCSI_ABORT_SUCCESS; } /* Fail abortion, if we're on the bus */ if (current_SC) { sti(); - return -1; + return SCSI_ABORT_BUSY; } /* look for command in disconnected queue */ @@ -852,7 +852,7 @@ SETBITS(SCSISEQ, ENSELO | ENAUTOATNO ); SETBITS( DMACNTRL0, INTEN ); - abort_result=0; + abort_result=SCSI_ABORT_SUCCESS; sti(); /* sleep until the abortion is complete */ @@ -864,7 +864,7 @@ /* command wasn't found */ sti(); - return 0; + return SCSI_ABORT_NOT_RUNNING; } /* @@ -922,6 +922,10 @@ show_queues(); + /* FIXME - if the device implements soft resets, the command will still + be running after the bus reset. In this case we should do nothing + and let the command continue. -ERY */ + if(current_SC) { current_SC->host_scribble = NULL; @@ -951,7 +955,7 @@ SETPORT( DMACNTRL0, INTEN ); } - return 0; + return SCSI_RESET_SUCCESS; } /* @@ -1246,7 +1250,7 @@ if(current_SC->SCp.phase & aborted) { - abort_result=1; + abort_result=SCSI_ABORT_ERROR; wake_up( &abortion_complete ); } @@ -1304,7 +1308,7 @@ #if defined(DEBUG_ABORT) printk("(ABORT) selection timeout, "); #endif - abort_result=1; + abort_result=SCSI_ABORT_ERROR; wake_up( &abortion_complete ); } @@ -1390,7 +1394,7 @@ if(message==ABORT) { /* revive abort(); abort() enables interrupts */ - abort_result=0; + abort_result=SCSI_ABORT_SUCCESS; wake_up( &abortion_complete ); current_SC->SCp.phase = (current_SC->SCp.phase & ~(P_MASK<<16)); diff -u --recursive --new-file v1.1.14/linux/drivers/scsi/aha152x.h linux/drivers/scsi/aha152x.h --- v1.1.14/linux/drivers/scsi/aha152x.h Sat Mar 26 15:08:16 1994 +++ linux/drivers/scsi/aha152x.h Tue May 24 09:19:18 1994 @@ -14,7 +14,7 @@ const char *aha152x_info(void); int aha152x_command(Scsi_Cmnd *); int aha152x_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -int aha152x_abort(Scsi_Cmnd *, int); +int aha152x_abort(Scsi_Cmnd *); int aha152x_reset(Scsi_Cmnd *); int aha152x_biosparam(int, int, int*); @@ -39,7 +39,8 @@ /* sg_tablesize */ SG_ALL, \ /* cmd_per_lun */ 1, \ /* present */ 0, \ - /* unchecked_isa_dma */ 0 } + /* unchecked_isa_dma */ 0, \ + /* use_clustering */ DISABLE_CLUSTERING } #endif diff -u --recursive --new-file v1.1.14/linux/drivers/scsi/aha1542.c linux/drivers/scsi/aha1542.c --- v1.1.14/linux/drivers/scsi/aha1542.c Sat May 7 14:54:03 1994 +++ linux/drivers/scsi/aha1542.c Tue May 24 09:19:19 1994 @@ -2,6 +2,7 @@ * linux/kernel/aha1542.c * * Copyright (C) 1992 Tommy Thorn + * Copyright (C) 1993, 1994 Eric Youngdale * * Modified by Eric Youngdale * Use request_irq and request_dma to help prevent unexpected conflicts @@ -75,6 +76,7 @@ #define WAITnexttimeout 3000000 static void setup_mailboxes(int base_io, struct Scsi_Host * shpnt); +static int aha1542_restart(struct Scsi_Host * shost); #define aha1542_intr_reset(base) outb(IRST, CONTROL(base)) @@ -215,7 +217,9 @@ /* Reset the adapter. I ought to make a hard reset, but it's not really nessesary */ /* DEB(printk("aha1542_test_port called \n")); */ - + + /* In case some other card was probing here, reset interrupts */ + aha1542_intr_reset(bse); /* reset interrupts, so they don't block */ outb(SRST|IRST/*|SCRST*/, CONTROL(bse)); i = jiffies + 2; @@ -259,7 +263,7 @@ outb(IRST, CONTROL(bse)); debug = 11; - + return debug; /* 1 = ok */ fail: return 0; /* 0 = not ok */ @@ -281,7 +285,8 @@ int number_serviced; struct Scsi_Host * shost; Scsi_Cmnd * SCtmp; - int irqno, * irqp; + int irqno, * irqp, flag; + int needs_restart; struct mailbox * mb; struct ccb *ccb; @@ -297,7 +302,7 @@ #ifdef DEBUG { - int flag = inb(INTRFLAGS(shost->io_port)); + flag = inb(INTRFLAGS(shost->io_port)); printk("aha1542_intr_handle: "); if (!(flag&ANYINTR)) printk("no interrupt?"); if (flag&MBIF) printk("MBIF "); @@ -308,8 +313,24 @@ }; #endif number_serviced = 0; + needs_restart = 0; while(1==1){ + flag = inb(INTRFLAGS(shost->io_port)); + + /* Check for unusual interrupts. If any of these happen, we should + probably do something special, but for now just printing a message + is sufficient. A SCSI reset detected is something that we really + need to deal with in some way. */ + if (flag & ~MBIF) { + if (flag&MBOA) printk("MBOF "); + if (flag&HACC) printk("HACC "); + if (flag&SCRD) { + needs_restart = 1; + printk("SCRD "); + } + } + aha1542_intr_reset(shost->io_port); cli(); @@ -325,8 +346,11 @@ if(mb[mbi].status == 0){ sti(); /* Hmm, no mail. Must have read it the last time around */ - if (number_serviced) return; - printk("aha1542.c: interrupt received, but no mail.\n"); + if (!number_serviced && !needs_restart) + printk("aha1542.c: interrupt received, but no mail.\n"); + /* We detected a reset. Restart all pending commands for + devices that use the hard reset option */ + if(needs_restart) aha1542_restart(shost); return; }; @@ -354,6 +378,8 @@ if (!SCtmp || !SCtmp->scsi_done) { printk("aha1542_intr_handle: Unexpected interrupt\n"); + printk("tarstat=%x, hastat=%x idlun=%x ccb#=%d \n", ccb[mbo].tarstat, + ccb[mbo].hastat, ccb[mbo].idlun, mbo); return; } @@ -883,39 +909,156 @@ return count; } +static int aha1542_restart(struct Scsi_Host * shost) +{ + int i; + int count = 0; +#if 0 + unchar ahacmd = CMD_START_SCSI; +#endif + + for(i=0; i< AHA1542_MAILBOXES; i++) + if(HOSTDATA(shost)->SCint[i] && + !(HOSTDATA(shost)->SCint[i]->device->soft_reset)) + { +#if 0 + HOSTDATA(shost)->mb[i].status = 1; /* Indicate ready to restart... */ +#endif + count++; + } + + printk("Potential to restart %d stalled commands...\n", count); +#if 0 + /* start scsi command */ + if (count) aha1542_out(shost->io_port, &ahacmd, 1); +#endif + return 0; +} + /* The abort command does not leave the device in a clean state where it is available to be used again. Until this gets worked out, we will leave it commented out. */ -int aha1542_abort(Scsi_Cmnd * SCpnt, int i) +int aha1542_abort(Scsi_Cmnd * SCpnt) { #if 0 - unchar ahacmd = CMD_START_SCSI; - int mbo; + int intval[3]; + unchar ahacmd = CMD_START_SCSI; + struct mailbox * mb; + int mbi, mbo, i; + + printk("In aha1542_abort: %x %x\n", + inb(STATUS(SCpnt->host->io_port)), + inb(INTRFLAGS(SCpnt->host->io_port))); + + cli(); + mb = HOSTDATA(SCpnt->host)->mb; + mbi = HOSTDATA(SCpnt->host)->aha1542_last_mbi_used + 1; + if (mbi >= 2*AHA1542_MAILBOXES) mbi = AHA1542_MAILBOXES; + + do{ + if(mb[mbi].status != 0) break; + mbi++; + if (mbi >= 2*AHA1542_MAILBOXES) mbi = AHA1542_MAILBOXES; + } while (mbi != HOSTDATA(SCpnt->host)->aha1542_last_mbi_used); + sti(); + + if(mb[mbi].status) { + printk("Lost interrupt discovered on irq %d - attempting to recover\n", + SCpnt->host->irq); + intval[0] = SCpnt->host->irq; + aha1542_intr_handle((int) &intval[2]); + return 0; + } + + /* OK, no lost interrupt. Try looking to see how many pending commands + we think we have. */ + + for(i=0; i< AHA1542_MAILBOXES; i++) + if(HOSTDATA(SCpnt->host)->SCint[i]) + { + if(HOSTDATA(SCpnt->host)->SCint[i] == SCpnt) { + printk("Timed out command pending for %4.4x\n", SCpnt->request.dev); + if (HOSTDATA(SCpnt->host)->mb[i].status) { + printk("OGMB still full - restarting\n"); + aha1542_out(SCpnt->host->io_port, &ahacmd, 1); + }; + } else + printk("Other pending command %4.4x\n", SCpnt->request.dev); + } + #endif + DEB(printk("aha1542_abort\n")); #if 0 cli(); for(mbo = 0; mbo < AHA1542_MAILBOXES; mbo++) if (SCpnt == HOSTDATA(SCpnt->host)->SCint[mbo]){ mb[mbo].status = 2; /* Abort command */ - aha1542_out(&ahacmd, 1); /* start scsi command */ + aha1542_out(SCpnt->host->io_port, &ahacmd, 1); /* start scsi command */ sti(); break; }; #endif - return 0; + return SCSI_ABORT_SNOOZE; } -/* We do not implement a reset function here, but the upper level code assumes - that it will get some kind of response for the command in SCpnt. We must - oblige, or the command will hang the scsi system */ +/* We do not implement a reset function here, but the upper level code + assumes that it will get some kind of response for the command in + SCpnt. We must oblige, or the command will hang the scsi system. + For a first go, we assume that the 1542 notifies us with all of the + pending commands (it does implement soft reset, after all). */ int aha1542_reset(Scsi_Cmnd * SCpnt) { + unchar ahacmd = CMD_START_SCSI; + int i; + DEB(printk("aha1542_reset called\n")); - if(SCpnt) SCpnt->flags |= NEEDS_JUMPSTART; - return 0; +#if 0 + /* This does a scsi reset for all devices on the bus */ + outb(SCRST, CONTROL(SCpnt->host->io_port)); +#else + /* This does a selective reset of just the one device */ + /* First locate the ccb for this command */ + for(i=0; i< AHA1542_MAILBOXES; i++) + if(HOSTDATA(SCpnt->host)->SCint[i] == SCpnt) + { + HOSTDATA(SCpnt->host)->ccb[i].op = 0x81; /* BUS DEVICE RESET */ + /* Now tell the 1542 to flush all pending commands for this target */ + aha1542_out(SCpnt->host->io_port, &ahacmd, 1); + + /* Here is the tricky part. What to do next. Do we get an interrupt + for the commands that we aborted with the specified target, or + do we generate this on our own? Try it without first and see + what happens */ + printk("Sent BUS DEVICE RESET to target %d\n", SCpnt->target); + + /* If the first does not work, then try the second. I think the + first option is more likely to be correct. Free the command + block for all commands running on this target... */ +#if 1 + for(i=0; i< AHA1542_MAILBOXES; i++) + if(HOSTDATA(SCpnt->host)->SCint[i] && + HOSTDATA(SCpnt->host)->SCint[i]->target == SCpnt->target) + { + Scsi_Cmnd * SCtmp; + SCtmp = HOSTDATA(SCpnt->host)->SCint[i]; + SCtmp->result = DID_RESET << 16; + if (SCtmp->host_scribble) scsi_free(SCtmp->host_scribble, 512); + printk("Sending DID_RESET for target %d\n", SCpnt->target); + SCtmp->scsi_done(SCpnt); + + HOSTDATA(SCpnt->host)->SCint[i] = NULL; + } + return SCSI_RESET_SUCCESS; +#else + return SCSI_RESET_PENDING; +#endif + } + +#endif + return SCSI_RESET_PENDING; } #ifdef CONFIG_BLK_DEV_SD diff -u --recursive --new-file v1.1.14/linux/drivers/scsi/aha1542.h linux/drivers/scsi/aha1542.h --- v1.1.14/linux/drivers/scsi/aha1542.h Fri Dec 17 08:20:31 1993 +++ linux/drivers/scsi/aha1542.h Tue May 24 09:19:19 1994 @@ -131,7 +131,7 @@ int aha1542_detect(int); int aha1542_command(Scsi_Cmnd *); int aha1542_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -int aha1542_abort(Scsi_Cmnd *, int); +int aha1542_abort(Scsi_Cmnd *); const char *aha1542_info(void); int aha1542_reset(Scsi_Cmnd *); int aha1542_biosparam(int, int, int*); @@ -152,6 +152,6 @@ NULL, \ aha1542_biosparam, \ AHA1542_MAILBOXES, 7, AHA1542_SCATTER, AHA1542_CMDLUN \ - , 0, 1} + , 0, 1, ENABLE_CLUSTERING} #endif diff -u --recursive --new-file v1.1.14/linux/drivers/scsi/aha1740.c linux/drivers/scsi/aha1740.c --- v1.1.14/linux/drivers/scsi/aha1740.c Wed Dec 1 14:44:16 1993 +++ linux/drivers/scsi/aha1740.c Tue May 24 09:19:22 1994 @@ -474,10 +474,10 @@ knees. I cannot (at this moment in time) think of any reason to reset the card once it's running. So there. */ -int aha1740_abort(Scsi_Cmnd * SCpnt, int i) +int aha1740_abort(Scsi_Cmnd * SCpnt) { DEB(printk("aha1740_abort called\n")); - return 0; + return SCSI_ABORT_SNOOZE; } /* We do not implement a reset function here, but the upper level code assumes @@ -487,8 +487,7 @@ int aha1740_reset(Scsi_Cmnd * SCpnt) { DEB(printk("aha1740_reset called\n")); - if (SCpnt) SCpnt->flags |= NEEDS_JUMPSTART; - return 0; + return SCSI_RESET_SNOOZE; } int aha1740_biosparam(int size, int dev, int* ip) diff -u --recursive --new-file v1.1.14/linux/drivers/scsi/aha1740.h linux/drivers/scsi/aha1740.h --- v1.1.14/linux/drivers/scsi/aha1740.h Wed Dec 1 14:44:16 1993 +++ linux/drivers/scsi/aha1740.h Tue May 24 09:19:19 1994 @@ -155,7 +155,7 @@ int aha1740_detect(int); int aha1740_command(Scsi_Cmnd *); int aha1740_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -int aha1740_abort(Scsi_Cmnd *, int); +int aha1740_abort(Scsi_Cmnd *); const char *aha1740_info(void); int aha1740_reset(Scsi_Cmnd *); int aha1740_biosparam(int, int, int*); @@ -174,7 +174,7 @@ aha1740_reset, \ NULL, \ aha1740_biosparam, \ - AHA1740_ECBS, 7, AHA1740_SCATTER, 1, 0, 0} + AHA1740_ECBS, 7, AHA1740_SCATTER, 1, 0, 0, ENABLE_CLUSTERING} #endif diff -u --recursive --new-file v1.1.14/linux/drivers/scsi/buslogic.c linux/drivers/scsi/buslogic.c --- v1.1.14/linux/drivers/scsi/buslogic.c Thu Jan 1 02:00:00 1970 +++ linux/drivers/scsi/buslogic.c Tue May 24 09:19:23 1994 @@ -0,0 +1,1203 @@ +/* + * buslogic.c (C) 1993 David B. Gentzel + * Low-level scsi driver for BusLogic adapters + * by David B. Gentzel, Whitfield Software Services, Carnegie, PA + * (gentzel@nova.enet.dec.com) + * Thanks to BusLogic for providing the necessary documentation + * + * The original version of this driver was derived from aha1542.[ch] which + * is Copyright (C) 1992 Tommy Thorn. Much has been reworked, but most of + * basic structure and substantial chunks of code still remain. + */ + +/* + * TODO: + * 1. Cleanup error handling & reporting. + * 2. Find out why scatter/gather is limited to 16 requests per command. + * 3. Add multiple outstanding requests. + * 4. See if we can make good use of having more than one command per lun. + * 5. Test/improve/fix abort & reset functions. + * 6. Look at command linking. + */ + +/* + * NOTES: + * BusLogic (formerly BusTek) manufactures an extensive family of + * intelligent, high performance SCSI-2 host adapters. They all support + * command queueing and scatter/gather I/O. Most importantly, they all + * support identical programming interfaces, so a single driver can be used + * for all boards. + * + * Actually, they all support TWO identical programming interfaces! They + * have an Adaptec 154x compatible interface (complete with 24 bit + * addresses) as well as a "native" 32 bit interface. As such, the Linux + * aha1542 driver can be used to drive them, but with less than optimal + * performance (at least for the EISA, VESA, and MCA boards). + * + * Here is the scoop on the various models: + * BT-542B - ISA first-party DMA with floppy support. + * BT-545S - 542B + FAST SCSI and active termination. + * BT-545D - 545S + differential termination. + * BT-445S - VESA bus-master FAST SCSI with active termination and floppy + * support. + * BT-640A - MCA bus-master with floppy support. + * BT-646S - 640A + FAST SCSI and active termination. + * BT-646D - 646S + differential termination. + * BT-742A - EISA bus-master with floppy support. + * BT-747S - 742A + FAST SCSI, active termination, and 2.88M floppy. + * BT-747D - 747S + differential termination. + * BT-757S - 747S + WIDE SCSI. + * BT-757D - 747D + WIDE SCSI. + * + * Should you require further information on any of these boards, BusLogic + * can be reached at (408)492-9090. + * + * This driver SHOULD support all of these boards. It has only been tested + * with a 747S. An earlier version was tested with a 445S. + * + * Places flagged with a triple question-mark are things which are either + * unfinished, questionable, or wrong. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "../block/blk.h" +#include "scsi.h" +#include "hosts.h" +#ifdef CONFIG_BLK_DEV_SD +# include "sd.h" +#endif +#define BUSLOGIC_PRIVATE_H /* Get the "private" stuff */ +#include "buslogic.h" + +#ifndef BUSLOGIC_DEBUG +# define BUSLOGIC_DEBUG UD_ABORT +#endif + +#define BUSLOGIC_VERSION "1.00" + +/* ??? This *MAY* work to properly report the geometry of disks > 1G when the + alternate geometry is enabled on the host adapter. It is completely + untested as I have no such disk to experiment with. I rarely refuse gifts, + however... */ +/* Check out the stuff in aha1542.c - is this the same as how buslogic does + it? - ERY */ +/* ??? Not Yet Implemented */ +/*#ifdef BUSLOGIC_ALTERNATE_MAPPING*/ + +/* Not a random value - if this is too large, the system hangs for a long time + waiting for something to happen if a board is not installed. */ +#define WAITNEXTTIMEOUT 3000000 + +/* This is for the scsi_malloc call in buslogic_queuecommand. */ +/* ??? I'd up this to 4096, but would we be in danger of using up the + scsi_malloc memory pool? */ +/* This could be a concern, I guess. It may be possible to fix things so that + the table generated in sd.c is compatible with the low-level code, but + don't hold your breath. -ERY */ +#define BUSLOGIC_SG_MALLOC 512 + +/* Since the SG list is malloced, we have to limit the length. */ +#define BUSLOGIC_MAX_SG (BUSLOGIC_SG_MALLOC / sizeof (struct chain)) + +/* The DMA-Controller. We need to fool with this because we want to be able to + use an ISA BusLogic without having to have the BIOS enabled. */ +#define DMA_MODE_REG 0xD6 +#define DMA_MASK_REG 0xD4 +#define CASCADE 0xC0 + +#define BUSLOGIC_MAILBOXES 16 /* ??? Arbitrary? */ + +/* BusLogic boards can be configured for quite a number of port addresses (six + to be exact), but I generally do not want the driver poking around at + random. We allow two port addresses - this allows people to use a BusLogic + with a MIDI card, which frequently also used 0x330. If different port + addresses are needed (e.g. to install more than two cards), you must define + BUSLOGIC_PORT_OVERRIDE to be a list of the addresses which will be checked. + This can also be used to resolve a conflict if the port-probing at a + standard port causes problems with another board. */ +static const unsigned int bases[] = { +#ifdef BUSLOGIC_PORT_OVERRIDE + BUSLOGIC_PORT_OVERRIDE +#else + 0x330, 0x334, /* 0x130, 0x134, 0x230, 0x234 */ +#endif +}; + +#define BIOS_TRANSLATION_6432 1 /* Default case */ +#define BIOS_TRANSLATION_25563 2 /* Big disk case */ + +struct hostdata { + unsigned char bus_type; + int bios_translation; /* Mapping bios uses - for compatibility */ + size_t last_mbi_used; + size_t last_mbo_used; + Scsi_Cmnd *SCint[BUSLOGIC_MAILBOXES]; + struct mailbox mb[2 * BUSLOGIC_MAILBOXES]; + struct ccb ccbs[BUSLOGIC_MAILBOXES]; +}; + +#define HOSTDATA(host) ((struct hostdata *)&(host)->hostdata) + +/* One for each IRQ level (9-15), although 13 will never be used. */ +static struct Scsi_Host *host[7] = { NULL, }; + +static int setup_mailboxes(unsigned int base, struct Scsi_Host *SHpnt); + +#define INTR_RESET(base) outb(RINT, CONTROL(base)) + +#define buslogic_printk buslogic_prefix(),printk + +#define CHECK(cond) if (cond) ; else goto fail + +#define WAIT(port, mask, allof, noneof) CHECK(wait(port, mask, allof, noneof)) +#define WAIT_WHILE(port, mask) WAIT(port, mask, 0, mask) +#define WAIT_UNTIL(port, mask) WAIT(port, mask, mask, 0) + +static __inline__ int wait(unsigned short port, unsigned char mask, + unsigned char allof, unsigned char noneof) +{ + int bits; + unsigned int timeout = WAITNEXTTIMEOUT; + + for (;;) { + bits = inb(port) & mask; + if ((bits & allof) == allof && (bits & noneof) == 0) + break; + if (--timeout == 0) + return FALSE; + } + return TRUE; +} + +static void buslogic_prefix(void) +{ + printk("BusLogic SCSI: "); +} + +#if 0 +static void buslogic_stat(unsigned int base) +{ + int s = inb(STATUS(base)), i = inb(INTERRUPT(base)); + + printk("status=%02X intrflags=%02X\n", s, i); +} +#else +# define buslogic_stat(base) +#endif + +/* This is a bit complicated, but we need to make sure that an interrupt + routine does not send something out while we are in the middle of this. + Fortunately, it is only at boot time that multi-byte messages are ever + sent. */ +static int buslogic_out(unsigned int base, const unsigned char *cmdp, size_t len) +{ + if (len == 1) { + for (;;) { + WAIT_WHILE(STATUS(base), CPRBSY); + cli(); + if (!(inb(STATUS(base)) & CPRBSY)) { + outb(*cmdp, COMMAND_PARAMETER(base)); + sti(); + return FALSE; + } + sti(); + } + } else { + cli(); + while (len--) { + WAIT_WHILE(STATUS(base), CPRBSY); + outb(*cmdp++, COMMAND_PARAMETER(base)); + } + sti(); + } + return FALSE; + fail: + sti(); + buslogic_printk("buslogic_out failed(%u): ", len + 1); + buslogic_stat(base); + return TRUE; +} + +static int buslogic_in(unsigned int base, unsigned char *cmdp, size_t len) +{ + cli(); + while (len--) { + WAIT_UNTIL(STATUS(base), DIRRDY); + *cmdp++ = inb(DATA_IN(base)); + } + sti(); + return FALSE; + fail: + sti(); + buslogic_printk("buslogic_in failed(%u): ", len + 1); + buslogic_stat(base); + return TRUE; +} + +static unsigned int makecode(unsigned int hosterr, unsigned int scsierr) +{ + switch (hosterr) { + case 0x00: /* Normal completion. */ + case 0x0A: /* Linked command complete without error and linked + normally. */ + case 0x0B: /* Linked command complete without error, interrupt + generated. */ + hosterr = DID_OK; + break; + + case 0x11: /* Selection time out: the initiator selection or + target reselection was not complete within the SCSI + Time out period. */ + hosterr = DID_TIME_OUT; + break; + + case 0x14: /* Target bus phase sequence failure - An invalid bus + phase or bus phase sequence was requested by the + target. The host adapter will generate a SCSI + Reset Condition, notifying the host with a RSTS + interrupt. */ + hosterr = DID_RESET; /* ??? Is this right? */ + break; + + case 0x12: /* Data overrun/underrun: the target attempted to + transfer more data than was allocated by the Data + Length field or the sum of the Scatter/Gather Data + Length fields. */ + case 0x13: /* Unexpected bus free - The target dropped the SCSI + BSY at an unexpected time. */ + case 0x15: /* MBO command was not 00, 01, or 02 - The first byte + of the MB was invalid. This usually indicates a + software failure. */ + case 0x16: /* Invalid CCB Operation Code - The first byte of the + CCB was invalid. This usually indicates a software + failure. */ + case 0x17: /* Linked CCB does not have the same LUN - A + subsequent CCB of a set of linked CCB's does not + specify the same logical unit number as the + first. */ + case 0x18: /* Invalid Target Direction received from Host - The + direction of a Target Mode CCB was invalid. */ + case 0x19: /* Duplicate CCB Received in Target Mode - More than + once CCB was received to service data transfer + between the same target LUN and initiator SCSI ID + in the same direction. */ + case 0x1A: /* Invalid CCB or Segment List Parameter - A segment + list with a zero length segment or invalid segment + list boundaries was received. A CCB parameter was + invalid. */ + case 0x1B: /* Auto request sense failed. */ + case 0x1C: /* SCSI-2 tagged queueing message was rejected by the + target. */ + case 0x20: /* The host adapter hardware failed. */ + case 0x21: /* The target did not respond to SCSI ATN and the host + adapter consequently issued a SCSI bus reset to + clear up the failure. */ + case 0x22: /* The host adapter asserted a SCSI bus reset. */ + case 0x23: /* Other SCSI devices asserted a SCSI bus reset. */ +#if BUSLOGIC_DEBUG + buslogic_printk("%X %X\n", hosterr, scsierr); +#endif + hosterr = DID_ERROR; /* ??? Couldn't find any better. */ + break; + + default: + buslogic_printk("makecode: unknown hoststatus %X\n", hosterr); + break; + } + return (hosterr << 16) | scsierr; +} + +static int test_port(unsigned int base, struct Scsi_Host *SHpnt) +{ + unsigned int i; + unsigned char inquiry_cmd[] = { CMD_INQUIRY }; + unsigned char inquiry_result[4]; + unsigned char *cmdp; + int len; + volatile int debug = 0; + + /* Quick and dirty test for presence of the card. */ + if (inb(STATUS(base)) == 0xFF) + return TRUE; + + /* Reset the adapter. I ought to make a hard reset, but it's not really + necessary. */ + +#if BUSLOGIC_DEBUG + buslogic_printk("test_port called\n"); +#endif + + outb(RSOFT | RINT/* | RSBUS*/, CONTROL(base)); + + /* Wait a little bit for things to settle down. */ + i = jiffies + 2; + while (i > jiffies); + + debug = 1; + /* Expect INREQ and HARDY, any of the others are bad. */ + WAIT(STATUS(base), STATMASK, INREQ | HARDY, + DACT | DFAIL | CMDINV | DIRRDY | CPRBSY); + + debug = 2; + /* Shouldn't have generated any interrupts during reset. */ + if (inb(INTERRUPT(base)) & INTRMASK) + goto fail; + + /* Perform a host adapter inquiry instead so we do not need to set up the + mailboxes ahead of time. */ + buslogic_out(base, inquiry_cmd, 1); + + debug = 3; + len = 4; + cmdp = &inquiry_result[0]; + while (len--) { + WAIT(STATUS(base), DIRRDY, DIRRDY, 0); + *cmdp++ = inb(DATA_IN(base)); + } + + debug = 4; + /* Reading port should reset DIRRDY. */ + if (inb(STATUS(base)) & DIRRDY) + goto fail; + + debug = 5; + /* When CMDC, command is completed, and we're though testing. */ + WAIT_UNTIL(INTERRUPT(base), CMDC); + + /* now initialize adapter. */ + + debug = 6; + /* Clear interrupts. */ + outb(RINT, CONTROL(base)); + + debug = 7; + + return FALSE; /* 0 = ok */ + fail: + return TRUE; /* 1 = not ok */ +} + +const char *buslogic_info(void) +{ + return "BusLogic SCSI Driver version " BUSLOGIC_VERSION; +} + +/* A "high" level interrupt handler. */ +static void buslogic_interrupt(int junk) +{ + void (*my_done)(Scsi_Cmnd *) = NULL; + int errstatus, mbistatus = 0, number_serviced, found; + size_t mbi, mbo = 0; + struct Scsi_Host *SHpnt; + Scsi_Cmnd *SCtmp; + int irqno, base; + struct mailbox *mb; + struct ccb *ccb; + + /* Magic - this -2 is only required for slow interrupt handlers */ + irqno = ((int *)junk)[-2]; + + SHpnt = host[irqno - 9]; + if (!SHpnt) + panic("buslogic.c: NULL SCSI host entry"); + + mb = HOSTDATA(SHpnt)->mb; + ccb = HOSTDATA(SHpnt)->ccbs; + base = SHpnt->io_port; + +#if BUSLOGIC_DEBUG + { + int flag = inb(INTERRUPT(base)); + + buslogic_printk("buslogic_interrupt: "); + if (!(flag & INTV)) + printk("no interrupt? "); + if (flag & IMBL) + printk("IMBL "); + if (flag & MBOR) + printk("MBOR "); + if (flag & CMDC) + printk("CMDC "); + if (flag & RSTS) + printk("RSTS "); + printk("status %02X\n", inb(STATUS(base))); + } +#endif + + number_serviced = 0; + + for (;;) { + INTR_RESET(base); + + cli(); + + mbi = HOSTDATA(SHpnt)->last_mbi_used + 1; + if (mbi >= 2 * BUSLOGIC_MAILBOXES) + mbi = BUSLOGIC_MAILBOXES; + + /* I use the "found" variable as I like to keep cli/sti pairs at the + same block level. Debugging dropped sti's is no fun... */ + + found = FALSE; + do { + if (mb[mbi].status != MBX_NOT_IN_USE) { + found = TRUE; + break; + } + mbi++; + if (mbi >= 2 * BUSLOGIC_MAILBOXES) + mbi = BUSLOGIC_MAILBOXES; + } while (mbi != HOSTDATA(SHpnt)->last_mbi_used); + + if (found) { + mbo = (struct ccb *)mb[mbi].ccbptr - ccb; + mbistatus = mb[mbi].status; + mb[mbi].status = MBX_NOT_IN_USE; + HOSTDATA(SHpnt)->last_mbi_used = mbi; + } + + sti(); + + if (!found) { + /* Hmm, no mail. Must have read it the last time around. */ + if (number_serviced) + return; + buslogic_printk("interrupt received, but no mail\n"); + return; + } + +#if BUSLOGIC_DEBUG + if (ccb[mbo].tarstat || ccb[mbo].hastat) + buslogic_printk("buslogic_interrupt: returning %08X (status %d)\n", + ((int)ccb[mbo].hastat << 16) | ccb[mbo].tarstat, + mb[mbi].status); +#endif + + if (mbistatus == 0x03) /* ??? 0x03 == Aborted CCB not found. */ + continue; + +#if BUSLOGIC_DEBUG + buslogic_printk("...done %u %u\n", mbo, mbi); +#endif + + SCtmp = HOSTDATA(SHpnt)->SCint[mbo]; + + if (!SCtmp || !SCtmp->scsi_done) { + buslogic_printk("buslogic_interrupt: Unexpected interrupt\n"); + return; + } + + my_done = SCtmp->scsi_done; + if (SCtmp->host_scribble) + scsi_free(SCtmp->host_scribble, BUSLOGIC_SG_MALLOC); + + /* ??? more error checking left out here */ + if (mbistatus != 1) + /* ??? This is surely wrong, but I don't know what's right. */ + errstatus = makecode(ccb[mbo].hastat, ccb[mbo].tarstat); + else + errstatus = 0; + +#if BUSLOGIC_DEBUG + if (errstatus) + buslogic_printk("error: %08X %04X %04X\n", + errstatus, ccb[mbo].hastat, ccb[mbo].tarstat); + + if (status_byte(ccb[mbo].tarstat) == CHECK_CONDITION) { + size_t i; + + buslogic_printk("buslogic_interrupt: sense: "); + for (i = 0; i < sizeof SCtmp->sense_buffer; i++) + printk(" %02X", SCtmp->sense_buffer[i]); + printk("\n"); + } + + if (errstatus) + buslogic_printk("buslogic_interrupt: returning %08X\n", errstatus); +#endif + + SCtmp->result = errstatus; + HOSTDATA(SHpnt)->SCint[mbo] = NULL; /* This effectively frees up + the mailbox slot, as far as + queuecommand is concerned. */ + my_done(SCtmp); + number_serviced++; + } +} + +int buslogic_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) +{ + static const unsigned char buscmd[] = { CMD_START_SCSI }; + unsigned char direction; + unsigned char *cmd = (unsigned char *)SCpnt->cmnd; + unsigned char target = SCpnt->target; + unsigned char lun = SCpnt->lun; + void *buff = SCpnt->request_buffer; + int bufflen = SCpnt->request_bufflen; + int mbo; + struct mailbox *mb; + struct ccb *ccb; + +#if BUSLOGIC_DEBUG + if (target > 1) { + SCpnt->result = DID_TIME_OUT << 16; + done(SCpnt); + return 0; + } +#endif + + if (*cmd == REQUEST_SENSE) { +#ifndef DEBUG + if (bufflen != sizeof SCpnt->sense_buffer) { + buslogic_printk("Wrong buffer length supplied for request sense (%d)\n", + bufflen); + panic("buslogic.c: wrong buffer length for request sense"); + } +#endif + SCpnt->result = 0; + done(SCpnt); + return 0; + } + +#if BUSLOGIC_DEBUG + { + int i; + + if (*cmd == READ_10 || *cmd == WRITE_10) + i = xscsi2int(cmd + 2); + else if (*cmd == READ_6 || *cmd == WRITE_6) + i = scsi2int(cmd + 2); + else + i = -1; + buslogic_printk("buslogic_queuecommand: dev %d cmd %02X pos %d len %d ", + target, *cmd, i, bufflen); + buslogic_stat(SCpnt->host->io_port); + buslogic_printk("buslogic_queuecommand: dumping scsi cmd: "); + for (i = 0; i < (COMMAND_SIZE(*cmd)); i++) + printk(" %02X", cmd[i]); + printk("\n"); + if (*cmd == WRITE_10 || *cmd == WRITE_6) + return 0; /* we are still testing, so *don't* write */ + } +#endif + + mb = HOSTDATA(SCpnt->host)->mb; + ccb = HOSTDATA(SCpnt->host)->ccbs; + + /* Use the outgoing mailboxes in a round-robin fashion, because this + is how the host adapter will scan for them. */ + + cli(); + + mbo = HOSTDATA(SCpnt->host)->last_mbo_used + 1; + if (mbo >= BUSLOGIC_MAILBOXES) + mbo = 0; + + do { + if (mb[mbo].status == MBX_NOT_IN_USE + && HOSTDATA(SCpnt->host)->SCint[mbo] == NULL) + break; + mbo++; + if (mbo >= BUSLOGIC_MAILBOXES) + mbo = 0; + } while (mbo != HOSTDATA(SCpnt->host)->last_mbo_used); + + if (mb[mbo].status != MBX_NOT_IN_USE || HOSTDATA(SCpnt->host)->SCint[mbo]) { + /* ??? Instead of panicing, we should enable OMBR interrupts and + sleep until we get one. */ + panic("buslogic.c: unable to find empty mailbox"); + } + + HOSTDATA(SCpnt->host)->SCint[mbo] = SCpnt; /* This will effectively + prevent someone else from + screwing with this cdb. */ + + HOSTDATA(SCpnt->host)->last_mbo_used = mbo; + + sti(); + +#if BUSLOGIC_DEBUG + buslogic_printk("sending command (%d %08X)...", mbo, done); +#endif + + /* This gets trashed for some reason */ + mb[mbo].ccbptr = &ccb[mbo]; + + memset(&ccb[mbo], 0, sizeof (struct ccb)); + + ccb[mbo].cdblen = COMMAND_SIZE(*cmd); /* SCSI Command Descriptor + Block Length */ + + direction = 0; + if (*cmd == READ_10 || *cmd == READ_6) + direction = 8; + else if (*cmd == WRITE_10 || *cmd == WRITE_6) + direction = 16; + + memcpy(ccb[mbo].cdb, cmd, ccb[mbo].cdblen); + + if (SCpnt->use_sg) { + struct scatterlist *sgpnt; + struct chain *cptr; + size_t i; + + ccb[mbo].op = CCB_OP_INIT_SG; /* SCSI Initiator Command w/scatter-gather */ + SCpnt->host_scribble = (unsigned char *)scsi_malloc(BUSLOGIC_SG_MALLOC); + if (SCpnt->host_scribble == NULL) + panic("buslogic.c: unable to allocate DMA memory"); + sgpnt = (struct scatterlist *)SCpnt->request_buffer; + cptr = (struct chain *)SCpnt->host_scribble; + if (SCpnt->use_sg > SCpnt->host->sg_tablesize) { + buslogic_printk("buslogic_queuecommand bad segment list, %d > %d\n", + SCpnt->use_sg, SCpnt->host->sg_tablesize); + panic("buslogic.c: bad segment list"); + } + for (i = 0; i < SCpnt->use_sg; i++) { + cptr[i].dataptr = sgpnt[i].address; + cptr[i].datalen = sgpnt[i].length; + } + ccb[mbo].datalen = SCpnt->use_sg * sizeof (struct chain); + ccb[mbo].dataptr = cptr; +#if BUSLOGIC_DEBUG + { + unsigned char *ptr; + + buslogic_printk("cptr %08X: ", cptr); + ptr = (unsigned char *)cptr; + for (i = 0; i < 18; i++) + printk(" %02X", ptr[i]); + printk("\n"); + } +#endif + } else { + ccb[mbo].op = CCB_OP_INIT; /* SCSI Initiator Command */ + SCpnt->host_scribble = NULL; + ccb[mbo].datalen = bufflen; + ccb[mbo].dataptr = buff; + } + ccb[mbo].id = target; + ccb[mbo].lun = lun; + ccb[mbo].dir = direction; + ccb[mbo].rsalen = sizeof SCpnt->sense_buffer; + ccb[mbo].senseptr = SCpnt->sense_buffer; + ccb[mbo].linkptr = NULL; + ccb[mbo].commlinkid = 0; + +#if BUSLOGIC_DEBUG + { + size_t i; + + buslogic_printk("buslogic_queuecommand: sending..."); + for (i = 0; i < sizeof ccb[mbo]; i++) + printk(" %02X", ((unsigned char *)&ccb[mbo])[i]); + printk("\n"); + } +#endif + + if (done) { +#if BUSLOGIC_DEBUG + buslogic_printk("buslogic_queuecommand: now waiting for interrupt: "); + buslogic_stat(SCpnt->host->io_port); +#endif + SCpnt->scsi_done = done; + mb[mbo].status = MBX_ACTION_START; + /* start scsi command */ + buslogic_out(SCpnt->host->io_port, buscmd, sizeof buscmd); +#if BUSLOGIC_DEBUG + buslogic_printk("buslogic_queuecommand: status: "); + buslogic_stat(SCpnt->host->io_port); +#endif + } else + buslogic_printk("buslogic_queuecommand: done can't be NULL\n"); + + return 0; +} + +#if 0 +static void internal_done(Scsi_Cmnd *SCpnt) +{ + SCpnt->SCp.Status++; +} + +int buslogic_command(Scsi_Cmnd *SCpnt) +{ +#if BUSLOGIC_DEBUG + buslogic_printk("buslogic_command: ..calling buslogic_queuecommand\n"); +#endif + + buslogic_queuecommand(SCpnt, internal_done); + + SCpnt->SCp.Status = 0; + while (!SCpnt->SCp.Status) + continue; + return SCpnt->result; + return internal_done_errcode; +} +#endif + +/* Initialize mailboxes. */ +static int setup_mailboxes(unsigned int base, struct Scsi_Host *SHpnt) +{ + size_t i; + int ok = FALSE; /* Innocent until proven guilty... */ + struct mailbox *mb = HOSTDATA(SHpnt)->mb; + struct ccb *ccb = HOSTDATA(SHpnt)->ccbs; + struct { + unsigned char cmd, count; + void *base PACKED; + } cmd = { CMD_INITEXTMB, BUSLOGIC_MAILBOXES, mb }; + + for (i = 0; i < BUSLOGIC_MAILBOXES; i++) { + mb[i].status = mb[BUSLOGIC_MAILBOXES + i].status = MBX_NOT_IN_USE; + mb[i].ccbptr = &ccb[i]; + } + INTR_RESET(base); /* reset interrupts, so they don't block */ + + /* If this fails, this must be an Adaptec board */ + if (buslogic_out(base, (unsigned char *)&cmd, sizeof cmd)) + goto must_be_adaptec; + + /* Wait until host adapter is done messing around, and then check to see + if the command was accepted. If it failed, this must be an Adaptec + board. */ + WAIT_UNTIL(STATUS(base), HARDY); + if (inb(STATUS(base)) & CMDINV) + goto must_be_adaptec; + + WAIT_UNTIL(INTERRUPT(base), CMDC); + while (0) { + fail: + buslogic_printk("buslogic_detect: failed setting up mailboxes\n"); + } + ok = TRUE; + must_be_adaptec: + INTR_RESET(base); + printk("- must be Adaptec\n"); /* So that the adaptec detect looks clean */ + return ok; +} + +static int getconfig(unsigned int base, unsigned char *irq, + unsigned char *dma, unsigned char *id, + unsigned char *bus_type, unsigned short *max_sg) +{ + unsigned char inquiry_cmd[2]; + unsigned char inquiry_result[4]; + int i; + + i = inb(STATUS(base)); + if (i & DIRRDY) + i = inb(DATA_IN(base)); + inquiry_cmd[0] = CMD_RETCONF; + buslogic_out(base, inquiry_cmd, 1); + buslogic_in(base, inquiry_result, 3); + WAIT_UNTIL(INTERRUPT(base), CMDC); + INTR_RESET(base); + /* Defer using the DMA value until we know the bus type. */ + *dma = inquiry_result[0]; + switch (inquiry_result[1]) { + case 0x01: + *irq = 9; + break; + case 0x02: + *irq = 10; + break; + case 0x04: + *irq = 11; + break; + case 0x08: + *irq = 12; + break; + case 0x20: + *irq = 14; + break; + case 0x40: + *irq = 15; + break; + default: + buslogic_printk("Unable to determine BusLogic IRQ level. Disabling board.\n"); + return TRUE; + } + *id = inquiry_result[2] & 0x7; + + inquiry_cmd[0] = CMD_INQEXTSETUP; + inquiry_cmd[1] = 4; + if (buslogic_out(base, inquiry_cmd, 2) + || buslogic_in(base, inquiry_result, 4)) + return TRUE; + WAIT_UNTIL(INTERRUPT(base), CMDC); + INTR_RESET(base); + +#ifdef BUSLOGIC_BUS_TYPE_OVERRIDE + *bus_type = BUS_TYPE_OVERRIDE; +#else + *bus_type = inquiry_result[0]; +#endif + CHECK(*bus_type == 'A' || *bus_type == 'E' || *bus_type == 'M'); +#ifdef BUSLOGIC_BUS_TYPE_OVERRIDE + if (inquiry_result[0] != BUS_TYPE_OVERRIDE) + buslogic_printk("Overriding bus type %c with %c\n", + inquiry_result[0], BUS_TYPE_OVERRIDE); +#endif + *max_sg = (inquiry_result[3] << 8) | inquiry_result[2]; + + /* We only need a DMA channel for ISA boards. Some other types of boards + (such as the 747S) have an option to report a DMA channel even though + none is used (for compatability with Adaptec drivers which require a + DMA channel). We ignore this. */ + if (*bus_type == 'A') + switch (*dma) { + case 0: /* This indicates a that no DMA channel is used. */ + *dma = 0; + break; + case 0x20: + *dma = 5; + break; + case 0x40: + *dma = 6; + break; + case 0x80: + *dma = 7; + break; + default: + buslogic_printk("Unable to determine BusLogic DMA channel. Disabling board.\n"); + return TRUE; + } + else + *dma = 0; + + while (0) { + fail: + buslogic_printk("buslogic_detect: query board settings\n"); + return TRUE; + } + + return FALSE; +} + +/* Query the board to find out the model. */ +static int buslogic_query(unsigned int base, int *trans) +{ +#if 0 + unsigned const char inquiry_cmd[] = { CMD_INQUIRY }; + unsigned char inquiry_result[4]; + int i; + + i = inb(STATUS(base)); + if (i & DIRRDY) + i = inb(DATA_IN(base)); + buslogic_out(base, inquiry_cmd, sizeof inquiry_cmd); + buslogic_in(base, inquiry_result, 4); + WAIT_UNTIL(INTERRUPT(base), CMDC); + while (0) { + fail: + buslogic_printk("buslogic_detect: query card type\n"); + } + INTR_RESET(base); +#endif + + *trans = BIOS_TRANSLATION_6432; /* Default case */ + + return FALSE; +} + +/* return non-zero on detection */ +int buslogic_detect(int hostnum) +{ + unsigned char dma; + unsigned char irq; + unsigned int base = 0; + unsigned char id; + unsigned char bus_type; + unsigned short max_sg; + int trans; + struct Scsi_Host *SHpnt = NULL; + int count = 0; + int indx; + int val; + +#if BUSLOGIC_DEBUG + buslogic_printk("buslogic_detect:\n"); +#endif + + for (indx = 0; indx < ARRAY_SIZE(bases); indx++) + if (!check_region(bases[indx], 3)) { + SHpnt = scsi_register(hostnum, sizeof (struct hostdata)); + + base = bases[indx]; + + if (test_port(base, SHpnt)) + goto unregister; + + /* Set the Bus on/off-times as not to ruin floppy performance. */ + { + /* The default ON/OFF times for BusLogic adapters is 7/4. */ + static const unsigned char oncmd[] = { CMD_BUSON_TIME, 7 }; + static const unsigned char offcmd[] = { CMD_BUSOFF_TIME, 5 }; + + INTR_RESET(base); + buslogic_out(base, oncmd, sizeof oncmd); + WAIT_UNTIL(INTERRUPT(base), CMDC); + /* CMD_BUSOFF_TIME is a noop for EISA boards, but as there is + no way to to differentiate EISA from VESA we send it + unconditionally. */ + INTR_RESET(base); + buslogic_out(base, offcmd, sizeof offcmd); + WAIT_UNTIL(INTERRUPT(base), CMDC); + while (0) { + fail: + buslogic_printk("buslogic_detect: setting bus on/off-time failed\n"); + } + INTR_RESET(base); + } + + if (buslogic_query(base, &trans)) + goto unregister; + + if (getconfig(base, &irq, &dma, &id, &bus_type, &max_sg)) + goto unregister; + +#if BUSLOGIC_DEBUG + buslogic_stat(base); +#endif + /* Here is where we tell the men from the boys (i.e. an Adaptec + will fail in setup_mailboxes, the men will not :-) */ + if (!setup_mailboxes(base, SHpnt)) + goto unregister; + + printk("Configuring BusLogic %s HA at port 0x%03X, IRQ %u", + (bus_type == 'A' ? "ISA" + : (bus_type == 'E' ? "EISA/VESA" : "MCA")), + base, irq); + if (dma != 0) + printk(", DMA %u", dma); + printk(", ID %u\n", id); + +#if BUSLOGIC_DEBUG + buslogic_stat(base); +#endif + +#if BUSLOGIC_DEBUG + buslogic_printk("buslogic_detect: enable interrupt channel %d\n", + irq); +#endif + + cli(); + val = request_irq(irq, buslogic_interrupt); + if (val) { + buslogic_printk("Unable to allocate IRQ for " + "BusLogic controller.\n"); + sti(); + goto unregister; + } + + if (dma) { + if (request_dma(dma)) { + buslogic_printk("Unable to allocate DMA channel for " + "BusLogic controller.\n"); + free_irq(irq); + sti(); + goto unregister; + } + + if (dma >= 5) { + outb((dma - 4) | CASCADE, DMA_MODE_REG); + outb(dma - 4, DMA_MASK_REG); + } + } + + host[irq - 9] = SHpnt; + SHpnt->this_id = id; + /* Only type 'A' (AT/ISA) bus adapters use unchecked DMA. */ + SHpnt->unchecked_isa_dma = (bus_type == 'A'); + SHpnt->sg_tablesize = max_sg; + if (SHpnt->sg_tablesize > BUSLOGIC_MAX_SG) + SHpnt->sg_tablesize = BUSLOGIC_MAX_SG; + /* ??? If we can dynamically allocate the mailbox arrays, I'll + probably bump up this number. */ + SHpnt->hostt->can_queue = BUSLOGIC_MAILBOXES; + /*SHpnt->base = ???;*/ + SHpnt->io_port = base; + SHpnt->dma_channel = dma; + SHpnt->irq = irq; + HOSTDATA(SHpnt)->bios_translation = trans; + if (trans == BIOS_TRANSLATION_25563) + buslogic_printk("Using extended bios translation.\n"); + HOSTDATA(SHpnt)->last_mbi_used = 2 * BUSLOGIC_MAILBOXES - 1; + HOSTDATA(SHpnt)->last_mbo_used = BUSLOGIC_MAILBOXES - 1; + memset(HOSTDATA(SHpnt)->SCint, 0, sizeof HOSTDATA(SHpnt)->SCint); + sti(); + +#if 0 + { + unsigned char buf[8]; + unsigned char cmd[] + = { READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + size_t i; + +#if BUSLOGIC_DEBUG + buslogic_printk("*** READ CAPACITY ***\n"); +#endif + for (i = 0; i < sizeof buf; i++) + buf[i] = 0x87; + for (i = 0; i < 2; i++) + if (!buslogic_command(i, cmd, buf, sizeof buf)) { + buslogic_printk("bus_detect: LU %u sector_size %d " + "device_size %d\n", + i, xscsi2int(buf + 4), xscsi2int(buf)); + } + +#if BUSLOGIC_DEBUG + buslogic_printk("*** NOW RUNNING MY OWN TEST ***\n"); +#endif + for (i = 0; i < 4; i++) { + static buffer[512]; + + cmd[0] = READ_10; + cmd[1] = 0; + xany2scsi(cmd + 2, i); + cmd[6] = 0; + cmd[7] = 0; + cmd[8] = 1; + cmd[9] = 0; + buslogic_command(0, cmd, buffer, sizeof buffer); + } + } +#endif + + snarf_region(bases[indx], 3); /* Register the IO ports that + we use */ + count++; + continue; + unregister: + scsi_unregister(SHpnt, sizeof (struct hostdata)); + } + return count; +} + +/* ??? The abort command for the aha1542 does not leave the device in a clean + state where it is available to be used again. As it is not clear whether + the same problem exists with BusLogic boards, we will enable this and see + if it works. */ +int buslogic_abort(Scsi_Cmnd *SCpnt) +{ + static const unsigned char buscmd[] = { CMD_START_SCSI }; + struct mailbox *mb; + int mbi, mbo, i; + + buslogic_printk("buslogic_abort: %X %X\n", + inb(STATUS(SCpnt->host->io_port)), + inb(INTERRUPT(SCpnt->host->io_port))); + + cli(); + mb = HOSTDATA(SCpnt->host)->mb; + mbi = HOSTDATA(SCpnt->host)->last_mbi_used + 1; + if (mbi >= 2 * BUSLOGIC_MAILBOXES) + mbi = BUSLOGIC_MAILBOXES; + + do { + if (mb[mbi].status != MBX_NOT_IN_USE) + break; + mbi++; + if (mbi >= 2 * BUSLOGIC_MAILBOXES) + mbi = BUSLOGIC_MAILBOXES; + } while (mbi != HOSTDATA(SCpnt->host)->last_mbi_used); + sti(); + + if (mb[mbi].status != MBX_NOT_IN_USE) { + buslogic_printk("Lost interrupt discovered on irq %d - attempting to recover\n", + SCpnt->host->irq); + { + int intval[3]; + + intval[0] = SCpnt->host->irq; + buslogic_interrupt((int)&intval[2]); + return SCSI_ABORT_SUCCESS; + } + } + + /* OK, no lost interrupt. Try looking to see how many pending commands we + think we have. */ + for (i = 0; i < BUSLOGIC_MAILBOXES; i++) + if (HOSTDATA(SCpnt->host)->SCint[i]) { + if (HOSTDATA(SCpnt->host)->SCint[i] == SCpnt) { + buslogic_printk("Timed out command pending for %4.4X\n", + SCpnt->request.dev); + if (HOSTDATA(SCpnt->host)->mb[i].status != MBX_NOT_IN_USE) { + buslogic_printk("OGMB still full - restarting\n"); + buslogic_out(SCpnt->host->io_port, buscmd, sizeof buscmd); + } + } else + buslogic_printk("Other pending command %4.4X\n", + SCpnt->request.dev); + } + +#if (BUSLOGIC_DEBUG & BD_ABORT) + buslogic_printk("buslogic_abort\n"); +#endif + +#if 1 + /* This section of code should be used carefully - some devices cannot + abort a command, and this merely makes it worse. */ + cli(); + for (mbo = 0; mbo < BUSLOGIC_MAILBOXES; mbo++) + if (SCpnt == HOSTDATA(SCpnt->host)->SCint[mbo]) { + HOSTDATA(SCpnt->host)->mb[mbo].status = MBX_ACTION_ABORT; + buslogic_out(SCpnt->host->io_port, buscmd, sizeof buscmd); + break; + } + sti(); +#endif + + return SCSI_ABORT_PENDING; +} + +/* We do not implement a reset function here, but the upper level code assumes + that it will get some kind of response for the command in SCpnt. We must + oblige, or the command will hang the SCSI system. */ +int buslogic_reset(Scsi_Cmnd *SCpnt) +{ +#if BUSLOGIC_DEBUG + buslogic_printk("buslogic_reset\n"); +#endif + return SCSI_RESET_SNOOZE; +} + +int buslogic_biosparam(int size, int dev, int *ip) +{ + /* ??? This is wrong if disk is configured for > 1G mapping. + Unfortunately, unlike UltraStor, I see know way of determining whether + > 1G mapping has been enabled. */ +#ifdef CONFIG_BLK_DEV_SD + int translation_algorithm; + Scsi_Device *disk; + + disk = rscsi_disks[MINOR(dev) >> 4].device; + translation_algorithm = HOSTDATA(disk->host)->bios_translation; + /* ??? Should this be > 1024, or >= 1024? Enquiring minds want to know. */ + if ((size >> 11) > 1024 + && translation_algorithm == BIOS_TRANSLATION_25563) { + /* Please verify that this is the same as what DOS returns */ + ip[0] = 255; + ip[1] = 63; + ip[2] = size / 255 / 63; + } else { + ip[0] = 64; + ip[1] = 32; + ip[2] = size >> 11; + } +/* if (ip[2] > 1024) + ip[2] = 1024; */ +#endif + return 0; +} diff -u --recursive --new-file v1.1.14/linux/drivers/scsi/buslogic.h linux/drivers/scsi/buslogic.h --- v1.1.14/linux/drivers/scsi/buslogic.h Thu Jan 1 02:00:00 1970 +++ linux/drivers/scsi/buslogic.h Tue May 24 09:19:22 1994 @@ -0,0 +1,175 @@ +/* + * buslogic.h (C) 1993 David B. Gentzel + * Low-level scsi driver for BusLogic adapters + * by David B. Gentzel, Whitfield Software Services, Carnegie, PA + * (gentzel@nova.enet.dec.com) + * Thanks to BusLogic for providing the necessary documentation + * + * The original version of this driver was derived from aha1542.[ch] which + * is Copyright (C) 1992 Tommy Thorn. Much has been reworked, but most of + * basic structure and substantial chunks of code still remain. + */ + +#ifndef _BUSLOGIC_H + +int buslogic_detect(int); +int buslogic_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); +int buslogic_abort(Scsi_Cmnd *); +const char *buslogic_info(void); +int buslogic_reset(Scsi_Cmnd *); +int buslogic_biosparam(int, int, int *); + +#define BUSLOGIC_CMDLUN 1 /* ??? */ + +#define BUSLOGIC { "BusLogic", \ + buslogic_detect, \ + buslogic_info, \ + 0, /* no command func */ \ + buslogic_queuecommand, \ + buslogic_abort, \ + buslogic_reset, \ + 0, /* slave_attach NYI */ \ + buslogic_biosparam, \ + 0, /* set by driver */ \ + 0, /* set by driver */ \ + 0, /* set by driver */ \ + BUSLOGIC_CMDLUN, \ + 0, \ + 0, /* set by driver */ \ + ENABLE_CLUSTERING \ + } + +#ifdef BUSLOGIC_PRIVATE_H + +/* ??? These don't really belong here */ +#ifndef TRUE +# define TRUE 1 +#endif +#ifndef FALSE +# define FALSE 0 +#endif + +#define ARRAY_SIZE(arr) (sizeof (arr) / sizeof (arr)[0]) + +#define PACKED __attribute__((packed)) + +#define BD_ABORT 0x0001 +#define BD_COMMAND 0x0002 +#define BD_DETECT 0x0004 +#define BD_INTERRUPT 0x0008 +#define BD_RESET 0x0010 + +/* I/O Port interface */ +/* READ */ +#define STATUS(base) (base) +#define DACT 0x80 /* Diagnostic Active */ +#define DFAIL 0x40 /* Diagonostic Failure */ +#define INREQ 0x20 /* Initialization Required */ +#define HARDY 0x10 /* Host Adapter Ready */ +#define CPRBSY 0x08 /* Command/Parameter Register Busy */ +#define DIRRDY 0x04 /* Data In Register Ready */ +#define CMDINV 0x01 /* Command Invalid */ +#define STATMASK 0xFD /* 0x02 is reserved */ + +#define DATA_IN(base) (STATUS(base) + 1) + +#define INTERRUPT(base) (STATUS(base) + 2) +#define INTV 0x80 /* Interrupt Valid */ +#define RSTS 0x08 /* SCSI Reset State */ +#define CMDC 0x04 /* Command Complete */ +#define MBOR 0x02 /* Mailbox Out Ready */ +#define IMBL 0x01 /* Incoming Mailbox Loaded */ +#define INTRMASK 0x8F /* 0x70 are reserved */ + +/* WRITE */ +#define CONTROL(base) STATUS(base) +#define RHARD 0x80 /* Hard Reset */ +#define RSOFT 0x40 /* Soft Reset */ +#define RINT 0x20 /* Interrupt Reset */ +#define RSBUS 0x10 /* SCSI Bus Reset */ + +#define COMMAND_PARAMETER(base) (STATUS(base) + 1) +#define CMD_TSTCMDCINT 0x00 /* Test CMDC Interrupt */ +#define CMD_INITMB 0x01 /* Initialize Mailbox */ +#define CMD_START_SCSI 0x02 /* Start Mailbox */ +#define CMD_START_BIOS 0x03 /* Start BIOS */ +#define CMD_INQUIRY 0x04 /* Inquire Board ID */ +#define CMD_ENBOMBRINT 0x05 /* Enable OMBR Interrupt */ +#define CMD_SETSELTIMOUT 0x06 /* Set SCSI Selection Time-Out */ +#define CMD_BUSON_TIME 0x07 /* Set Bus-On Time */ +#define CMD_BUSOFF_TIME 0x08 /* Set Bus-Off Time */ +#define CMD_BUSXFR_RATE 0x09 /* Set Bus Transfer Rate */ +#define CMD_INQ_DEVICES 0x0A /* Inquire Installed Devices */ +#define CMD_RETCONF 0x0B /* Return Configuration */ +#define CMD_TARGET_MODE 0x0C /* Set Target Mode */ +#define CMD_INQ_SETUP_INFO 0x0D /* Inquire Set-up Information */ +#define CMD_WRITE_LCL_RAM 0x1A /* Write Adapter Local RAM */ +#define CMD_READ_LCL_RAM 0x1B /* Read Adapter Local RAM */ +#define CMD_WRITE_BM_FIFO 0x1C /* Write Bus Master Chip FIFO */ +#define CMD_READ_BM_FIFO 0x1D /* Read Bus Master Chip FIFO */ +#define CMD_ECHO 0x1F /* Echo Data Byte */ +#define CMD_HA_DIAG 0x20 /* Host Adapter Diagnostic */ +#define CMD_HA_OPTIONS 0x21 /* Host Adapter Options */ +#define CMD_INITEXTMB 0x81 /* Initialize Extended Mailbox */ +#define CMD_INQEXTSETUP 0x8D /* Inquire Extended Set-up Information */ +#define CMD_WRITE_INQ_BUF 0x9A /* Write Inquery Data Buffer + (Target Mode Only) */ +#define CMD_READ_INQ_BUF 0x9B /* Read Inquery Data Buffer + (Target Mode Only) */ + +#define MBX_NOT_IN_USE 0x00 +#define MBX_ACTION_START 0x01 +#define MBX_ACTION_ABORT 0x02 +#define MBX_COMPLETION_OK 0x01 +#define MBX_COMPLETION_ABORTED 0x02 +#define MBX_COMPLETION_NOT_FOUND 0x03 +#define MBX_COMPLETION_ERROR 0x04 + +/* Mailbox Definition */ +struct mailbox { + void *ccbptr; /* lsb, ..., msb */ + unsigned char btstat; + unsigned char sdstat; + unsigned char reserved; + unsigned char status; /* Command/Status */ +}; + +/* This is used with scatter-gather */ +struct chain { + unsigned long datalen; /* Size of this part of chain */ + void *dataptr; /* Location of data */ +}; + +#define MAX_CDB 12 + +struct ccb { /* Command Control Block */ + unsigned char op; /* Command Control Block Operation Code */ + unsigned char dir; + unsigned char cdblen; /* SCSI Command Length */ + unsigned char rsalen; /* Request Sense Allocation Length/Disable */ + unsigned long datalen; /* Data Length (msb, ..., lsb) */ + void *dataptr; /* Data Pointer */ + unsigned char reserved[2]; + unsigned char hastat; /* Host Adapter Status (HASTAT) */ + unsigned char tarstat; /* Target Device Status */ + unsigned char id; + unsigned char lun; + unsigned char cdb[MAX_CDB]; + unsigned char ccbcontrol; + unsigned char commlinkid; /* Command Linking Identifier */ + void *linkptr; /* Link Pointer */ + void *senseptr; +}; + +#define CCB_OP_INIT 0x00 /* Initiator CCB */ +#define CCB_OP_TARG 0x01 /* Target CCB */ +#define CCB_OP_INIT_SG 0x02 /* Initiator CCB with scatter-gather */ +#define CCB_OP_INIT_R 0x03 /* Initiator CCB with residual data length + returned */ +#define CCB_OP_INIT_SG_R 0x04 /* Initiator CCB with scatter-gather and + residual data length returned */ +#define CCB_OP_BUS_RESET 0x81 /* SCSI bus device reset */ + +#endif + +#endif diff -u --recursive --new-file v1.1.14/linux/drivers/scsi/constants.c linux/drivers/scsi/constants.c --- v1.1.14/linux/drivers/scsi/constants.c Tue Feb 15 07:26:30 1994 +++ linux/drivers/scsi/constants.c Tue May 24 09:19:19 1994 @@ -73,7 +73,7 @@ static const char vendor[] = "VENDOR SPECIFIC"; static void print_opcode(int opcode) { - char **table = commands[ group(opcode) ]; + const char **table = commands[ group(opcode) ]; switch ((int) table) { case RESERVED_GROUP: printk("%s(0x%02x) ", reserved, opcode); @@ -351,8 +351,8 @@ static char *snstext[] = { "None","Recovered Error","Not Ready","Medium Error","Hardware Error", "Illegal Request","Unit Attention","Data Protect","Blank Check", - "Key=E","Key=F","Filemark","End-Of-Medium","Incorrect Block Length", - "14","15"}; + "Key=9","Copy Aborted","Aborted Command","End-Of-Medium", + "Volume Overflow", "Miscompare", "Key=15"}; #endif @@ -394,9 +394,6 @@ printk("%s error ", error); #if (CONSTANTS & CONST_SENSE) - if (sense_buffer[2] & 0x80) printk( "FMK "); - if (sense_buffer[2] & 0x40) printk( "EOM "); - if (sense_buffer[2] & 0x20) printk( "ILI "); printk( "%s%x: sense key %s\n", devclass, dev, snstext[sense_buffer[2] & 0x0f]); #else printk("%s%x: sns = %2x %2x\n", devclass, dev, sense_buffer[0], sense_buffer[2]); @@ -437,9 +434,12 @@ } done: +#if !(CONSTANTS & CONST_SENSE) + printk("Raw sense data:"); for (i = 0; i < s; ++i) printk("0x%02x ", sense_buffer[i]); - + printk("\n"); +#endif return; } diff -u --recursive --new-file v1.1.14/linux/drivers/scsi/fdomain.c linux/drivers/scsi/fdomain.c --- v1.1.14/linux/drivers/scsi/fdomain.c Tue Apr 19 10:53:18 1994 +++ linux/drivers/scsi/fdomain.c Tue May 24 09:19:19 1994 @@ -68,7 +68,7 @@ revision 10h, October 17, 1991) Private communications, Drew Eckhardt (drew@cs.colorado.edu) and Eric - Youngdale (eric@tantalus.nrl.navy.mil), 1992. + Youngdale (ericy@cais.com), 1992. Private communication, Tuong Le (Future Domain Engineering department), 1994. (Disk geometry computations for Future Domain BIOS version 3.4, and @@ -1394,9 +1394,8 @@ inb( port_base + Configuration2 ) ); } -int fdomain_16x0_abort( Scsi_Cmnd *SCpnt, int code ) +int fdomain_16x0_abort( Scsi_Cmnd *SCpnt) { - #if EVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT printk( "Future Domain: Abort " ); #endif @@ -1407,11 +1406,7 @@ printk( " (not in command)\n" ); #endif sti(); - return 0; - } else { -#if EVERY_ACCESS || ERRORS_ONLY - printk( " code = %d\n", code ); -#endif + return SCSI_ABORT_NOT_RUNNING; } #if DEBUG_ABORT @@ -1422,14 +1417,14 @@ current_SC->SCp.phase |= aborted; - current_SC->result = code ? code : DID_ABORT; + current_SC->result = DID_ABORT << 16; sti(); /* Aborts are not done well. . . */ - my_done( code << 16 ); + my_done( DID_ABORT << 16 ); - return 0; + return SCSI_ABORT_SUCCESS; } int fdomain_16x0_reset( Scsi_Cmnd *SCpnt ) @@ -1458,10 +1453,7 @@ is probably hosed at this point. We will, however, try to keep things going by informing the high-level code that we need help. */ - if (SCpnt) - SCpnt->flags |= NEEDS_JUMPSTART; - - return 0; + return SCSI_RESET_WAKEUP; } #ifdef CONFIG_BLK_DEV_SD diff -u --recursive --new-file v1.1.14/linux/drivers/scsi/fdomain.h linux/drivers/scsi/fdomain.h --- v1.1.14/linux/drivers/scsi/fdomain.h Tue Apr 19 10:52:15 1994 +++ linux/drivers/scsi/fdomain.h Tue May 24 09:19:19 1994 @@ -27,7 +27,7 @@ int fdomain_16x0_detect( int ); int fdomain_16x0_command( Scsi_Cmnd * ); -int fdomain_16x0_abort( Scsi_Cmnd *, int ); +int fdomain_16x0_abort( Scsi_Cmnd *); const char *fdomain_16x0_info( void ); int fdomain_16x0_reset( Scsi_Cmnd * ); int fdomain_16x0_queue( Scsi_Cmnd *, void (*done)(Scsi_Cmnd *) ); @@ -47,5 +47,5 @@ fdomain_16x0_reset, \ NULL, \ fdomain_16x0_biosparam, \ - 1, 6, 64 /* SG_NONE */, 1 ,0, 0 } + 1, 6, 64 /* SG_NONE */, 1 ,0, 0, DISABLE_CLUSTERING} #endif diff -u --recursive --new-file v1.1.14/linux/drivers/scsi/g_NCR5380.h linux/drivers/scsi/g_NCR5380.h --- v1.1.14/linux/drivers/scsi/g_NCR5380.h Wed Dec 1 14:44:16 1993 +++ linux/drivers/scsi/g_NCR5380.h Tue May 24 09:19:19 1994 @@ -33,7 +33,7 @@ #ifndef ASM -int generic_NCR5380_abort(Scsi_Cmnd *, int); +int generic_NCR5380_abort(Scsi_Cmnd *); int generic_NCR5380_detect(int); const char *generic_NCR5380_info(void); int generic_NCR5380_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); @@ -59,7 +59,7 @@ generic_NCR5380_queue_command, generic_NCR5380_abort, \ generic_NCR5380_reset, NULL, \ NULL, /* can queue */ CAN_QUEUE, /* id */ 7, SG_ALL, \ - /* cmd per lun */ CMD_PER_LUN , 0, 0} + /* cmd per lun */ CMD_PER_LUN , 0, 0, DISABLE_CLUSTERING} #else #define NCR5380_implementation_fields \ diff -u --recursive --new-file v1.1.14/linux/drivers/scsi/hosts.c linux/drivers/scsi/hosts.c --- v1.1.14/linux/drivers/scsi/hosts.c Wed Dec 1 14:44:16 1993 +++ linux/drivers/scsi/hosts.c Tue May 24 09:19:20 1994 @@ -39,6 +39,10 @@ #include "aha1740.h" #endif +#ifdef CONFIG_SCSI_BUSLOGIC +#include "buslogic.h" +#endif + #ifdef CONFIG_SCSI_FUTURE_DOMAIN #include "fdomain.h" #endif @@ -47,6 +51,10 @@ #include "g_NCR5380.h" #endif +#ifdef CONFIG_SCSI_IN2000 +#include "in2000.h" +#endif + #ifdef CONFIG_SCSI_PAS16 #include "pas16.h" #endif @@ -105,6 +113,10 @@ #ifdef CONFIG_SCSI_AHA152X AHA152X, #endif +/* Buslogic must come before aha1542.c */ +#ifdef CONFIG_SCSI_BUSLOGIC + BUSLOGIC, +#endif #ifdef CONFIG_SCSI_AHA1542 AHA1542, #endif @@ -114,6 +126,9 @@ #ifdef CONFIG_SCSI_FUTURE_DOMAIN FDOMAIN_16X0, #endif +#ifdef CONFIG_SCSI_IN2000 + IN2000, +#endif #ifdef CONFIG_SCSI_GENERIC_NCR5380 GENERIC_NCR5380, #endif @@ -181,6 +196,7 @@ retval->host_queue = NULL; retval->host_wait = NULL; retval->last_reset = 0; + retval->irq = 0; retval->hostt = &scsi_hosts[i]; retval->next = NULL; #ifdef DEBUG diff -u --recursive --new-file v1.1.14/linux/drivers/scsi/hosts.h linux/drivers/scsi/hosts.h --- v1.1.14/linux/drivers/scsi/hosts.h Wed Dec 1 14:44:16 1993 +++ linux/drivers/scsi/hosts.h Tue May 24 09:19:22 1994 @@ -21,16 +21,11 @@ */ -/* A jumpstart is often required when the reset() function is called - - many host adapters cannot do this cleanly, so they do nothing at all. - To get the command going again, these routines set this bit in the flags - so that a scsi_request_sense() is executed, and the command starts running - again */ - -#define NEEDS_JUMPSTART 0x20 - #define SG_NONE 0 -#define SG_ALL 0xff +#define SG_ALL 0x7fff + +#define DISABLE_CLUSTERING 0 +#define ENABLE_CLUSTERING 1 /* The various choices mean: NONE: Self evident. Host adapter is not capable of scatter-gather. @@ -109,7 +104,11 @@ /* Since the mid level driver handles time outs, etc, we want to be able to abort the current command. Abort returns 0 if the - abortion was successful. If non-zero, the code passed to it + abortion was successful. The field SCpnt->abort reason + can be filled in with the appropriate reason why we wanted + the abort in the first place, and this will be used + in the mid-level code instead of the host_byte(). + If non-zero, the code passed to it will be used as the return code, otherwise DID_ABORT should be returned. @@ -117,7 +116,7 @@ resetting the bus, etc. if necessary. */ - int (* abort)(Scsi_Cmnd *, int); + int (* abort)(Scsi_Cmnd *); /* The reset function will reset the SCSI bus. Any executing @@ -192,6 +191,15 @@ true if this host adapter uses unchecked DMA onto an ISA bus. */ unsigned unchecked_isa_dma:1; + /* + true if this host adapter can make good use of clustering. + I originally thought that if the tablesize was large that it + was a waste of CPU cycles to prepare a cluster list, but + it works out that the Buslogic is faster if you use a smaller + number of segments (i.e. use clustering). I guess it is + inefficient. + */ + unsigned use_clustering:1; } Scsi_Host_Template; /* diff -u --recursive --new-file v1.1.14/linux/drivers/scsi/pas16.h linux/drivers/scsi/pas16.h --- v1.1.14/linux/drivers/scsi/pas16.h Wed Dec 1 14:44:16 1993 +++ linux/drivers/scsi/pas16.h Tue May 24 09:19:20 1994 @@ -114,7 +114,7 @@ #ifndef ASM -int pas16_abort(Scsi_Cmnd *, int); +int pas16_abort(Scsi_Cmnd *); int pas16_biosparam(int, int, int*); int pas16_detect(int); const char *pas16_info(void); @@ -145,7 +145,7 @@ NULL, pas16_queue_command, pas16_abort, pas16_reset, NULL, \ pas16_biosparam, \ /* can queue */ CAN_QUEUE, /* id */ 7, SG_ALL, \ - /* cmd per lun */ CMD_PER_LUN , 0, 0} + /* cmd per lun */ CMD_PER_LUN , 0, 0, DISABLE_CLUSTERING} #else diff -u --recursive --new-file v1.1.14/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c --- v1.1.14/linux/drivers/scsi/scsi.c Tue Apr 19 10:52:47 1994 +++ linux/drivers/scsi/scsi.c Tue May 24 09:19:20 1994 @@ -1,5 +1,7 @@ /* * scsi.c Copyright (C) 1992 Drew Eckhardt + * Copyright (C) 1993, 1994 Eric Youngdale + * * generic mid-level SCSI driver by * Drew Eckhardt * @@ -10,7 +12,7 @@ * Tommy Thorn * Thomas Wuensche * - * Modified by Eric Youngdale eric@tantalus.nrl.navy.mil to + * Modified by Eric Youngdale ericy@cais.com to * add scatter-gather, multiple outstanding request, and other * enhancements. */ @@ -19,6 +21,7 @@ #include #include #include +#include #include "../block/blk.h" #include "scsi.h" @@ -84,8 +87,8 @@ #define WAS_TIMEDOUT 0x02 #define WAS_SENSE 0x04 #define IS_RESETTING 0x08 -#define ASKED_FOR_SENSE 0x10 -/* #define NEEDS_JUMPSTART 0x20 defined in hosts.h */ +#define IS_ABORTING 0x10 +#define ASKED_FOR_SENSE 0x20 /* * This is the number of clock ticks we should wait before we time out @@ -97,6 +100,11 @@ * respectively. */ +#ifdef DEBUG_TIMEOUT +static void scsi_dump_status(void); +#endif + + #ifdef DEBUG #define SCSI_TIMEOUT 500 #else @@ -350,6 +358,8 @@ type = -1; } + scsi_devices[NR_SCSI_DEVICES].soft_reset = + (scsi_result[7] & 1) && ((scsi_result[3] & 7) == 2); scsi_devices[NR_SCSI_DEVICES].random = (type == TYPE_TAPE) ? 0 : 1; scsi_devices[NR_SCSI_DEVICES].type = type; @@ -503,9 +513,13 @@ switch (SCpnt->internal_timeout & (IN_ABORT | IN_RESET)) { case NORMAL_TIMEOUT: - if (!in_scan) - printk("SCSI host %d timed out - aborting command\n", - SCpnt->host->host_no); + if (!in_scan) { + printk("SCSI host %d timed out - aborting command\n", + SCpnt->host->host_no); +#ifdef DEBUG_TIMEOUT + scsi_dump_status(); +#endif + } if (!scsi_abort (SCpnt, DID_TIME_OUT)) return; @@ -516,7 +530,13 @@ return; case IN_RESET: case (IN_ABORT | IN_RESET): - panic("Unable to reset scsi host %d\n",SCpnt->host->host_no); + /* This might be controversial, but if there is a bus hang, + you might conceivably want the machine up and running + esp if you have an ide disk. */ + printk("Unable to reset scsi host %d - ",SCpnt->host->host_no); + printk("probably a SCSI bus hang.\n"); + return; + default: INTERNAL_ERROR; } @@ -739,11 +759,26 @@ if (host->hostt->can_queue) { + extern unsigned long intr_count; #ifdef DEBUG printk("queuecommand : routine at %08x\n", host->hostt->queuecommand); #endif + /* This locking tries to prevent all sorts of races between + queuecommand and the interrupt code. In effect, + we are only allowed to be in queuecommand once at + any given time, and we can only be in the interrupt + handler and the queuecommand function at the same time + when queuecommand is called while servicing the + interrupt. */ + + if(!intr_count && SCpnt->host->irq) + disable_irq(SCpnt->host->irq); + host->hostt->queuecommand (SCpnt, scsi_done); + + if(!intr_count && SCpnt->host->irq) + enable_irq(SCpnt->host->irq); } else { @@ -876,6 +911,7 @@ /* Start the timer ticking. */ SCpnt->internal_timeout = 0; + SCpnt->abort_reason = 0; internal_cmnd (SCpnt); #ifdef DEBUG @@ -904,10 +940,12 @@ printk("performing request sense\n"); #endif +#if 0 /* FIXME - remove this when done */ if(SCpnt->flags & NEEDS_JUMPSTART) { SCpnt->flags &= ~NEEDS_JUMPSTART; scsi_request_sense (SCpnt); }; +#endif } @@ -997,6 +1035,18 @@ int result = SCpnt->result; oldto = update_timeout(SCpnt, 0); +#ifdef DEBUG_TIMEOUT + if(result) printk("Non-zero result in scsi_done %x %d:%d\n", + result, SCpnt->target, SCpnt->lun); +#endif + + /* If we requested an abort, (and we got it) then fix up the return + status to say why */ + if(host_byte(result) == DID_ABORT && SCpnt->abort_reason) + SCpnt->result = result = (result & 0xff00ffff) | + (SCpnt->abort_reason << 16); + + #define FINISHED 0 #define MAYREDO 1 #define REDO 3 @@ -1008,13 +1058,6 @@ switch (host_byte(result)) { case DID_OK: - if (SCpnt->flags & IS_RESETTING) - { - SCpnt->flags &= ~IS_RESETTING; - status = REDO; - break; - } - if (status_byte(result) && (SCpnt->flags & WAS_SENSE)) /* Failed to obtain sense information */ { @@ -1154,7 +1197,7 @@ printk("Host returned DID_TIME_OUT - "); #endif - if (SCpnt->flags & WAS_TIMEDOUT) + if (SCpnt->flags & WAS_TIMEDOUT) { #ifdef DEBUG printk("Aborting\n"); @@ -1167,6 +1210,7 @@ printk ("Retrying.\n"); #endif SCpnt->flags |= WAS_TIMEDOUT; + SCpnt->internal_timeout &= ~IN_ABORT; status = REDO; } break; @@ -1189,6 +1233,13 @@ exit = (DRIVER_INVALID | SUGGEST_ABORT); break; case DID_RESET: + if (SCpnt->flags & IS_RESETTING) + { + SCpnt->flags &= ~IS_RESETTING; + status = REDO; + break; + } + if(msg_byte(result) == GOOD && status_byte(result) == CHECK_CONDITION) { switch (check_sense(SCpnt)) { @@ -1305,7 +1356,7 @@ int scsi_abort (Scsi_Cmnd * SCpnt, int why) { - int temp, oldto; + int oldto; struct Scsi_Host * host = SCpnt->host; while(1) @@ -1321,22 +1372,67 @@ SCpnt->internal_timeout |= IN_ABORT; oldto = update_timeout(SCpnt, ABORT_TIMEOUT); - - sti(); - if (!host->host_busy || !host->hostt->abort(SCpnt, why)) - temp = 0; - else - temp = 1; + if ((SCpnt->flags & IS_RESETTING) && + SCpnt->device->soft_reset) { + /* OK, this command must have died when we did the + reset. The device itself must have lied. */ + printk("Stale command on %d:%d appears to have died when" + " the bus was reset\n", SCpnt->target, SCpnt->lun); + } - cli(); - SCpnt->internal_timeout &= ~IN_ABORT; - update_timeout(SCpnt, oldto); sti(); - return temp; + if (!host->host_busy) { + SCpnt->internal_timeout &= ~IN_ABORT; + update_timeout(SCpnt, oldto); + return 0; } - } - } - + SCpnt->abort_reason = why; + switch(host->hostt->abort(SCpnt)) { + /* We do not know how to abort. Try waiting another + time increment and see if this helps. Set the + WAS_TIMEDOUT flag set so we do not try this twice + */ + case SCSI_ABORT_BUSY: /* Tough call - returning 1 from + this is too severe */ + case SCSI_ABORT_SNOOZE: + if(why == DID_TIME_OUT) { + cli(); + SCpnt->internal_timeout &= ~IN_ABORT; + if(SCpnt->flags & WAS_TIMEDOUT) { + sti(); + return 1; /* Indicate we cannot handle this. + We drop down into the reset handler + and try again */ + } else { + SCpnt->flags |= WAS_TIMEDOUT; + oldto = SCpnt->timeout_per_command; + update_timeout(SCpnt, oldto); + } + sti(); + } + return 0; + case SCSI_ABORT_PENDING: + if(why != DID_TIME_OUT) { + cli(); + update_timeout(SCpnt, oldto); + sti(); + } + return 0; + case SCSI_ABORT_SUCCESS: + /* We should have already aborted this one. No + need to adjust timeout */ + case SCSI_ABORT_NOT_RUNNING: + SCpnt->internal_timeout &= ~IN_ABORT; + return 0; + case SCSI_ABORT_ERROR: + default: + SCpnt->internal_timeout &= ~IN_ABORT; + return 1; + } + } + } + } + int scsi_reset (Scsi_Cmnd * SCpnt) { int temp, oldto; @@ -1363,10 +1459,14 @@ sti(); SCpnt1 = host->host_queue; while(SCpnt1) { - if ((SCpnt1->request.dev > 0) && - !(SCpnt1->flags & IS_RESETTING) && + if (SCpnt1->request.dev > 0) { +#if 0 + if (!(SCpnt1->flags & IS_RESETTING) && !(SCpnt1->internal_timeout & IN_ABORT)) scsi_abort(SCpnt1, DID_RESET); +#endif + SCpnt1->flags |= IS_RESETTING; + } SCpnt1 = SCpnt1->next; }; @@ -1381,11 +1481,35 @@ host->last_reset = jiffies; host->host_busy--; } + + switch(temp) { + case SCSI_RESET_SUCCESS: + cli(); + SCpnt->internal_timeout &= ~IN_RESET; + update_timeout(SCpnt, oldto); + sti(); + return 0; + case SCSI_RESET_PENDING: + return 0; + case SCSI_RESET_WAKEUP: + SCpnt->internal_timeout &= ~IN_RESET; + scsi_request_sense (SCpnt); + return 0; + case SCSI_RESET_SNOOZE: + /* In this case, we set the timeout field to 0 + so that this command does not time out any more, + and we return 1 so that we get a message on the + screen. */ + cli(); + SCpnt->internal_timeout &= ~IN_RESET; + update_timeout(SCpnt, 0); + sti(); + /* If you snooze, you lose... */ + case SCSI_RESET_ERROR: + default: + return 1; + } - cli(); - SCpnt->internal_timeout &= ~IN_RESET; - update_timeout(SCpnt, oldto); - sti(); return temp; } } @@ -1405,6 +1529,7 @@ do { cli(); + update_timeout(NULL, 0); /* Find all timers such that they have 0 or negative (shouldn't happen) time remaining on them. @@ -1412,9 +1537,8 @@ timed_out = 0; for(host = scsi_hostlist; host; host = host->next) { - SCpnt = host->host_queue; - while (SCpnt){ - if (SCpnt->timeout > 0 && SCpnt->timeout <= time_elapsed) + for(SCpnt = host->host_queue; SCpnt; SCpnt = SCpnt->next) + if (SCpnt->timeout == -1) { sti(); SCpnt->timeout = 0; @@ -1422,10 +1546,7 @@ ++timed_out; cli(); } - SCpnt = SCpnt->next; - }; }; - update_timeout(NULL, 0); } while (timed_out); sti(); } @@ -1468,14 +1589,14 @@ least = 0xffffffff; - for(host = scsi_hostlist; host; host = host->next) { - SCpnt = host->host_queue; - while (SCpnt){ - if (SCpnt->timeout > 0 && (SCpnt->timeout -= used) < least) - least = SCpnt->timeout; - SCpnt = SCpnt->next; - }; - }; + for(host = scsi_hostlist; host; host = host->next) + for(SCpnt = host->host_queue; SCpnt; SCpnt = SCpnt->next) + if (SCpnt->timeout > 0) { + SCpnt->timeout -= used; + if(SCpnt->timeout <= 0) SCpnt->timeout = -1; + if(SCpnt->timeout > 0 && SCpnt->timeout < least) + least = SCpnt->timeout; + }; /* If something is due to timeout again, then we will set the next timeout @@ -1617,6 +1738,7 @@ if(scsi_devices[i].type != -1){ for(j=0;jhostt->cmd_per_lun;j++){ SCpnt->host = scsi_devices[i].host; + SCpnt->device = &scsi_devices[i]; SCpnt->target = scsi_devices[i].id; SCpnt->lun = scsi_devices[i].lun; SCpnt->index = i; @@ -1724,3 +1846,62 @@ else printk("\n"); } + +#ifdef DEBUG_TIMEOUT +static void +scsi_dump_status(void) +{ + int i, i1; + Scsi_Cmnd * SCpnt; + printk("Dump of scsi parameters:\n"); + SCpnt = last_cmnd; + for(i=0; ihostt->cmd_per_lun;i1++) + { + /* (0) 0:0:0 (802 123434 8 8 0) (3 3 2) (%d %d %d) %d %x */ + printk("(%d) %d:%d:%d (%4.4x %d %d %d %d) (%d %d %x) (%d %d %d) %x %x %d %x\n", + i, SCpnt->host->host_no, + SCpnt->target, + SCpnt->lun, + SCpnt->request.dev, + SCpnt->request.sector, + SCpnt->request.nr_sectors, + SCpnt->request.current_nr_sectors, + SCpnt->use_sg, + SCpnt->retries, + SCpnt->allowed, + SCpnt->flags, + SCpnt->timeout_per_command, + SCpnt->timeout, + SCpnt->internal_timeout, + SCpnt->cmnd[0], + SCpnt->sense_buffer[2], + (SCpnt->request.waiting ? + SCpnt->request.waiting->pid : 0), + SCpnt->result); + SCpnt++; + }; + printk("wait_for_request = %x\n", wait_for_request); + /* Now dump the request lists for each block device */ + printk("Dump of pending block device requests\n"); + for(i=0; idev, + req->cmd, + req->sector, + req->nr_sectors, + req->current_nr_sectors, + (req->waiting ? + req->waiting->pid : 0)); + req = req->next; + } + printk("\n"); + } +} +#endif diff -u --recursive --new-file v1.1.14/linux/drivers/scsi/scsi.h linux/drivers/scsi/scsi.h --- v1.1.14/linux/drivers/scsi/scsi.h Tue Apr 19 10:52:47 1994 +++ linux/drivers/scsi/scsi.h Tue May 24 09:19:20 1994 @@ -276,6 +276,7 @@ unsigned tagged_supported:1; /* Supports SCSI-II tagged queing */ unsigned tagged_queue:1; /*SCSI-II tagged queing enabled */ unsigned disconnect:1; /* can disconnect */ + unsigned soft_reset:1; /* Uses soft reset option */ unsigned char current_tag; /* current tag */ } Scsi_Device; /* @@ -315,6 +316,63 @@ #define CONTIGUOUS_BUFFERS(X,Y) ((X->b_data+X->b_size) == Y->b_data) +/* + * These are the return codes for the abort and reset functions. The mid-level + * code uses these to decide what to do next. Each of the low level abort + * and reset functions must correctly indicate what it has done. + */ + +/* We did not do anything. Wait + some more for this command to complete, and if this does not work, try + something more serious. */ +#define SCSI_ABORT_SNOOZE 0 + +/* This means that we were able to abort the command. We have already + called the mid-level done function, and do not expect an interrupt that will + lead to another call to the mid-level done function for this command */ +#define SCSI_ABORT_SUCCESS 1 + +/* We called for an abort of this command, and we should get an interrupt + when this succeeds. Thus we should not restore the timer for this + command in the mid-level abort function. */ +#define SCSI_ABORT_PENDING 2 + +/* Unable to abort - command is currently on the bus. Grin and bear it. */ +#define SCSI_ABORT_BUSY 3 + +/* The command is not active in the low level code. Command probably + finished. */ +#define SCSI_ABORT_NOT_RUNNING 4 + +/* Something went wrong. The low level driver will indicate the correct + error condition when it calls scsi_done, so the mid-level abort function + can simply wait until this comes through */ +#define SCSI_ABORT_ERROR 5 + +/* We do not know how to reset the bus, or we do not want to. Bummer. + Anyway, just wait a little more for the command in question, and hope that + it eventually finishes */ +#define SCSI_RESET_SNOOZE 0 + +/* This means that we were able to reset the bus. We have restarted all of + the commands that should be restarted, and we should be able to continue + on normally from here. We do not expect any interrupts that will return + DID_RESET to any of the other commands in the host_queue. */ +#define SCSI_RESET_SUCCESS 1 + +/* We called for an reset of this bus, and we should get an interrupt + when this succeeds. Each command should get it's own status + passed up to scsi_done, but this has not happened yet. */ +#define SCSI_RESET_PENDING 2 + +/* We did a reset, but do not expect an interrupt to signal DID_RESET. + This tells the upper level code to request the sense info, and this + should keep the command alive. */ +#define SCSI_RESET_WAKEUP 3 + +/* Something went wrong, and we do not know how to fix it. */ +#define SCSI_RESET_ERROR 4 + void * scsi_malloc(unsigned int); int scsi_free(void *, unsigned int); extern unsigned int dma_free_sectors; /* How much room do we have left */ @@ -340,6 +398,7 @@ typedef struct scsi_cmnd { struct Scsi_Host * host; + Scsi_Device * device; unsigned char target, lun, index; struct scsi_cmnd *next, *prev; @@ -355,6 +414,8 @@ sense info */ unsigned short use_sg; /* Number of pieces of scatter-gather */ unsigned short sglist_len; /* size of malloc'd scatter-gather list */ + unsigned short abort_reason; /* If the mid-level code requests an + abort, this is the reason. */ unsigned bufflen; /* Size of data buffer */ void *buffer; /* Data buffer */ diff -u --recursive --new-file v1.1.14/linux/drivers/scsi/scsi_debug.c linux/drivers/scsi/scsi_debug.c --- v1.1.14/linux/drivers/scsi/scsi_debug.c Tue Apr 19 10:52:48 1994 +++ linux/drivers/scsi/scsi_debug.c Tue May 24 09:19:22 1994 @@ -521,7 +521,7 @@ return 1; } -int scsi_debug_abort(Scsi_Cmnd * SCpnt,int i) +int scsi_debug_abort(Scsi_Cmnd * SCpnt) { int j; void (*my_done)(Scsi_Cmnd *); diff -u --recursive --new-file v1.1.14/linux/drivers/scsi/scsi_debug.h linux/drivers/scsi/scsi_debug.h --- v1.1.14/linux/drivers/scsi/scsi_debug.h Tue Apr 19 10:52:48 1994 +++ linux/drivers/scsi/scsi_debug.h Tue May 24 09:19:20 1994 @@ -23,5 +23,5 @@ scsi_debug_reset, \ NULL, \ scsi_debug_biosparam, \ - SCSI_DEBUG_MAILBOXES, 7, SG_ALL, 1, 0, 1} + SCSI_DEBUG_MAILBOXES, 7, SG_ALL, 1, 0, 1, ENABLE_CLUSTERING} #endif diff -u --recursive --new-file v1.1.14/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c --- v1.1.14/linux/drivers/scsi/sd.c Mon Apr 25 10:04:32 1994 +++ linux/drivers/scsi/sd.c Tue May 24 09:19:20 1994 @@ -1,11 +1,12 @@ /* * sd.c Copyright (C) 1992 Drew Eckhardt + * Copyright (C) 1993, 1994 Eric Youngdale * Linux scsi disk driver by * Drew Eckhardt * * * - * Modified by Eric Youngdale eric@tantalus.nrl.navy.mil to + * Modified by Eric Youngdale ericy@cais.com to * add scatter-gather, multiple outstanding request, and other * enhancements. */ @@ -40,7 +41,7 @@ #define SD_TIMEOUT 300 #define SD_MOD_TIMEOUT 750 -#define CLUSTERABLE_DEVICE(SC) (SC->host->sg_tablesize < 64 && \ +#define CLUSTERABLE_DEVICE(SC) (SC->host->hostt->use_clustering && \ scsi_devices[SC->index].type != TYPE_MOD) struct hd_struct * sd; diff -u --recursive --new-file v1.1.14/linux/drivers/scsi/seagate.c linux/drivers/scsi/seagate.c --- v1.1.14/linux/drivers/scsi/seagate.c Wed Dec 1 14:44:16 1993 +++ linux/drivers/scsi/seagate.c Tue May 24 09:19:20 1994 @@ -1546,14 +1546,11 @@ return retcode (st0x_aborted); } -int seagate_st0x_abort (Scsi_Cmnd * SCpnt, int code) +int seagate_st0x_abort (Scsi_Cmnd * SCpnt) { - if (code) - st0x_aborted = code; - else - st0x_aborted = DID_ABORT; - - return 0; + st0x_aborted = DID_ABORT; + + return SCSI_ABORT_PENDING; } /* @@ -1590,8 +1587,7 @@ #ifdef DEBUG printk("SCSI bus reset.\n"); #endif - if(SCpnt) SCpnt->flags |= NEEDS_JUMPSTART; - return 0; + return SCSI_RESET_PENDING; } #ifdef CONFIG_BLK_DEV_SD diff -u --recursive --new-file v1.1.14/linux/drivers/scsi/seagate.h linux/drivers/scsi/seagate.h --- v1.1.14/linux/drivers/scsi/seagate.h Wed Dec 1 14:44:16 1993 +++ linux/drivers/scsi/seagate.h Tue May 24 09:19:21 1994 @@ -16,7 +16,7 @@ int seagate_st0x_command(Scsi_Cmnd *); int seagate_st0x_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -int seagate_st0x_abort(Scsi_Cmnd *, int); +int seagate_st0x_abort(Scsi_Cmnd *); const char *seagate_st0x_info(void); int seagate_st0x_reset(Scsi_Cmnd *); @@ -34,7 +34,7 @@ seagate_st0x_info, seagate_st0x_command, \ seagate_st0x_queue_command, seagate_st0x_abort, \ seagate_st0x_reset, NULL, seagate_st0x_biosparam, \ - 1, 7, SG_ALL, 1, 0, 0} + 1, 7, SG_ALL, 1, 0, 0, DISABLE_CLUSTERING} #endif diff -u --recursive --new-file v1.1.14/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c --- v1.1.14/linux/drivers/scsi/sr.c Tue Apr 19 10:52:49 1994 +++ linux/drivers/scsi/sr.c Tue May 24 09:19:21 1994 @@ -1,5 +1,6 @@ /* - * sr.c by David Giller + * sr.c Copyright (C) 1992 David Giller + * Copyright (C) 1993, 1994 Eric Youngdale * * adapted from: * sd.c Copyright (C) 1992 Drew Eckhardt @@ -8,7 +9,7 @@ * * * - * Modified by Eric Youngdale eric@tantalus.nrl.navy.mil to + * Modified by Eric Youngdale ericy@cais.com to * add scatter-gather, multiple outstanding request, and other * enhancements. */ diff -u --recursive --new-file v1.1.14/linux/drivers/scsi/t128.h linux/drivers/scsi/t128.h --- v1.1.14/linux/drivers/scsi/t128.h Wed Dec 1 14:44:16 1993 +++ linux/drivers/scsi/t128.h Tue May 24 09:19:21 1994 @@ -91,7 +91,7 @@ #define T_DATA_REG_OFFSET 0x1e00 /* rw 512 bytes long */ #ifndef ASM -int t128_abort(Scsi_Cmnd *, int); +int t128_abort(Scsi_Cmnd *); int t128_biosparam(int, int, int*); int t128_detect(int); const char *t128_info(void); @@ -122,7 +122,7 @@ NULL, t128_queue_command, t128_abort, t128_reset, NULL, \ t128_biosparam, \ /* can queue */ CAN_QUEUE, /* id */ 7, SG_ALL, \ - /* cmd per lun */ CMD_PER_LUN , 0, 0} + /* cmd per lun */ CMD_PER_LUN , 0, 0, DISABLE_CLUSTERING} #else diff -u --recursive --new-file v1.1.14/linux/drivers/scsi/ultrastor.c linux/drivers/scsi/ultrastor.c --- v1.1.14/linux/drivers/scsi/ultrastor.c Mon Jan 24 09:55:21 1994 +++ linux/drivers/scsi/ultrastor.c Tue May 24 09:19:21 1994 @@ -6,7 +6,7 @@ * scatter/gather added by Scott Taylor (n217cg@tamuts.tamu.edu) * 24F and multiple command support by John F. Carr (jfc@athena.mit.edu) * John's work modified by Caleb Epstein (cae@jpmorgan.com) and - * Eric Youngdale (eric@tantalus.nrl.navy.mil). + * Eric Youngdale (ericy@cais.com). * Thanks to UltraStor for providing the necessary documentation */ @@ -796,7 +796,7 @@ */ -int ultrastor_abort(Scsi_Cmnd *SCpnt, int code) +int ultrastor_abort(Scsi_Cmnd *SCpnt) { #if ULTRASTOR_DEBUG & UD_ABORT char out[108]; @@ -807,7 +807,8 @@ unsigned char old_aborted; void (*done)(Scsi_Cmnd *); - if(config.slot) return 0; /* Do not attempt an abort for the 24f */ + if(config.slot) + return SCSI_ABORT_SNOOZE; /* Do not attempt an abort for the 24f */ mscp_index = ((struct mscp *)SCpnt->host_scribble) - config.mscp; if (mscp_index >= ULTRASTOR_MAX_CMDS) @@ -851,16 +852,16 @@ cli(); ultrastor_interrupt(0); restore_flags(flags); - return 0; + return SCSI_ABORT_SUCCESS; /* FIXME - is this correct? -ERY */ } #endif - old_aborted = xchgb(code ? code : DID_ABORT, &config.aborted[mscp_index]); + old_aborted = xchgb(DID_ABORT, &config.aborted[mscp_index]); /* aborted == 0xff is the signal that queuecommand has not yet sent the command. It will notice the new abort flag and fail. */ if (old_aborted == 0xff) - return 0; + return SCSI_ABORT_SUCCESS; /* On 24F, send an abort MSCP request. The adapter will interrupt and the interrupt handler will call done. */ @@ -879,7 +880,7 @@ printk(out, ogm_status, ogm_addr, icm_status, icm_addr); #endif restore_flags(flags); - return 0; + return SCSI_ABORT_PENDING; } #if ULTRASTOR_DEBUG & UD_ABORT @@ -891,13 +892,18 @@ still be using it. Setting SCint = 0 causes the interrupt handler to ignore the command. */ + /* FIXME - devices that implement soft resets will still be running + the command after a bus reset. We would probably rather leave + the command in the queue. The upper level code will automatically + leave the command in the active state instead of requeueing it. ERY */ + #if ULTRASTOR_DEBUG & UD_ABORT if (config.mscp[mscp_index].SCint != SCpnt) printk("abort: command mismatch, %x != %x\n", config.mscp[mscp_index].SCint, SCpnt); #endif if (config.mscp[mscp_index].SCint == 0) - return 1; + return SCSI_ABORT_NOT_RUNNING; if (config.mscp[mscp_index].SCint != SCpnt) panic("Bad abort"); config.mscp[mscp_index].SCint = 0; @@ -908,7 +914,7 @@ done(SCpnt); /* Need to set a timeout here in case command never completes. */ - return 0; + return SCSI_ABORT_SUCCESS; } @@ -920,10 +926,8 @@ printk("US14F: reset: called\n"); #endif - if(config.slot) { - if (SCpnt) SCpnt->flags |= NEEDS_JUMPSTART; - return 0; /* Do not attempt a reset for the 24f */ - }; + if(config.slot) + return SCSI_RESET_SNOOZE; /* Do not attempt a reset for the 24f */ save_flags(flags); cli(); @@ -958,6 +962,9 @@ } #endif + /* FIXME - if the device implements soft resets, then the command + will still be running. ERY */ + memset((unsigned char *)config.aborted, 0, sizeof config.aborted); #if ULTRASTOR_MAX_CMDS == 1 config.mscp_busy = 0; @@ -966,7 +973,7 @@ #endif restore_flags(flags); - return 0; + return SCSI_RESET_SUCCESS; } diff -u --recursive --new-file v1.1.14/linux/drivers/scsi/ultrastor.h linux/drivers/scsi/ultrastor.h --- v1.1.14/linux/drivers/scsi/ultrastor.h Wed Dec 1 14:44:16 1993 +++ linux/drivers/scsi/ultrastor.h Tue May 24 09:19:21 1994 @@ -16,7 +16,7 @@ int ultrastor_detect(int); const char *ultrastor_info(void); int ultrastor_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -int ultrastor_abort(Scsi_Cmnd *, int); +int ultrastor_abort(Scsi_Cmnd *); int ultrastor_reset(Scsi_Cmnd *); int ultrastor_biosparam(int, int, int *); @@ -31,7 +31,8 @@ { "UltraStor 14F/24F/34F", ultrastor_detect, ultrastor_info, 0, \ ultrastor_queuecommand, ultrastor_abort, ultrastor_reset, \ 0, ultrastor_biosparam, ULTRASTOR_MAX_CMDS, 0, \ - ULTRASTOR_14F_MAX_SG, ULTRASTOR_MAX_CMDS_PER_LUN, 0, 1 } + ULTRASTOR_14F_MAX_SG, ULTRASTOR_MAX_CMDS_PER_LUN, 0, 1, \ + ENABLE_CLUSTERING } #ifdef ULTRASTOR_PRIVATE diff -u --recursive --new-file v1.1.14/linux/drivers/scsi/wd7000.c linux/drivers/scsi/wd7000.c --- v1.1.14/linux/drivers/scsi/wd7000.c Mon May 23 12:14:24 1994 +++ linux/drivers/scsi/wd7000.c Tue May 24 09:19:21 1994 @@ -1185,18 +1185,17 @@ /* * I have absolutely NO idea how to do an abort with the WD7000... */ -int wd7000_abort(Scsi_Cmnd * SCpnt, int i) +int wd7000_abort(Scsi_Cmnd * SCpnt) { -#ifdef DEBUG - printk("wd7000_abort: Scsi_Cmnd = 0x%06x, code = %d ", (int) SCpnt, i); - printk("id %d lun %d cdb", SCpnt->target, SCpnt->lun); - { - int j; unchar *cdbj = (unchar *) SCpnt->cmnd; - for (j=0; j < COMMAND_SIZE(*cdbj); j++) printk(" %02x", *(cdbj++)); - printk(" result %08x\n", SCpnt->result); + Adapter *host = (Adapter *) SCpnt->host->hostdata; + + if (inb(host->iobase+ASC_STAT) & INT_IM) { + printk("wd7000_abort: lost interrupt\n"); + wd7000_intr_handle(host->irq); + return SCSI_ABORT_SUCCESS; } -#endif - return 0; + + return SCSI_ABORT_SNOOZE; } @@ -1205,21 +1204,7 @@ */ int wd7000_reset(Scsi_Cmnd * SCpnt) { -#ifdef DEBUG - printk("wd7000_reset: Scsi_Cmnd = 0x%06x ", (int) SCpnt); - if (SCpnt) { - printk("id %d lun %d cdb", SCpnt->target, SCpnt->lun); - { - int j; unchar *cdbj = (unchar *) SCpnt->cmnd; - for (j=0; j < COMMAND_SIZE(*cdbj); j++) - printk(" %02x", *(cdbj++)); - printk(" result %08x", SCpnt->result); - } - } - printk("\n"); -#endif - if (SCpnt) SCpnt->flags |= NEEDS_JUMPSTART; - return 0; + return SCSI_RESET_SNOOZE; } diff -u --recursive --new-file v1.1.14/linux/drivers/scsi/wd7000.h linux/drivers/scsi/wd7000.h --- v1.1.14/linux/drivers/scsi/wd7000.h Mon May 23 12:14:24 1994 +++ linux/drivers/scsi/wd7000.h Tue May 24 09:19:21 1994 @@ -15,7 +15,7 @@ int wd7000_detect(int); int wd7000_command(Scsi_Cmnd *); int wd7000_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -int wd7000_abort(Scsi_Cmnd *, int); +int wd7000_abort(Scsi_Cmnd *); const char *wd7000_info(void); int wd7000_reset(Scsi_Cmnd *); int wd7000_biosparam(int, int, int*); @@ -48,5 +48,5 @@ wd7000_reset, \ NULL, \ wd7000_biosparam, \ - WD7000_Q, 7, WD7000_SG, 1, 0, 1} + WD7000_Q, 7, WD7000_SG, 1, 0, 1, ENABLE_CLUSTERING} #endif diff -u --recursive --new-file v1.1.14/linux/fs/exec.c linux/fs/exec.c --- v1.1.14/linux/fs/exec.c Tue May 24 08:47:06 1994 +++ linux/fs/exec.c Wed May 25 15:31:46 1994 @@ -572,6 +572,8 @@ last_task_used_math = NULL; current->used_math = 0; current->personality = 0; + current->lcall7 = no_lcall7; + current->signal_map = current->signal_invmap = ident_map; } /* @@ -760,6 +762,25 @@ error = do_execve(filename, (char **) regs.ecx, (char **) regs.edx, ®s); putname(filename); return error; +} + +/* + * signal mapping: this is the default identity mapping used for normal + * linux binaries (it's both the reverse and the normal map, of course) + */ +unsigned long ident_map[33] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 +}; + +/* + * default lcall7 handler.. The native linux stuff doesn't + * use it at all, so we just segfault on it. + */ +asmlinkage void no_lcall7(struct pt_regs * regs) +{ + send_sig(SIGSEGV, current, 1); } static void set_brk(unsigned long start, unsigned long end) diff -u --recursive --new-file v1.1.14/linux/fs/ext/namei.c linux/fs/ext/namei.c --- v1.1.14/linux/fs/ext/namei.c Sat May 7 14:54:05 1994 +++ linux/fs/ext/namei.c Wed May 25 08:46:39 1994 @@ -543,8 +543,9 @@ retval = -EPERM; if (!(inode = iget(dir->i_sb, de->inode))) goto end_rmdir; - if ((dir->i_mode & S_ISVTX) && current->euid && - inode->i_uid != current->euid) + if ((dir->i_mode & S_ISVTX) && !suser() && + current->euid != inode->i_uid && + current->euid != dir->i_uid) goto end_rmdir; if (inode->i_dev != dir->i_dev) goto end_rmdir; diff -u --recursive --new-file v1.1.14/linux/fs/ext2/file.c linux/fs/ext2/file.c --- v1.1.14/linux/fs/ext2/file.c Tue Apr 19 10:53:21 1994 +++ linux/fs/ext2/file.c Wed May 25 09:02:46 1994 @@ -277,10 +277,6 @@ } p = (pos % sb->s_blocksize) + bh->b_data; pos += c; - if (pos > inode->i_size) { - inode->i_size = pos; - inode->i_dirt = 1; - } written += c; memcpy_fromfs (p, buf, c); buf += c; @@ -288,6 +284,8 @@ mark_buffer_dirty(bh, 0); brelse (bh); } + if (pos > inode->i_size) + inode->i_size = pos; up(&inode->i_sem); inode->i_ctime = inode->i_mtime = CURRENT_TIME; filp->f_pos = pos; diff -u --recursive --new-file v1.1.14/linux/fs/ext2/namei.c linux/fs/ext2/namei.c --- v1.1.14/linux/fs/ext2/namei.c Sat May 7 14:54:06 1994 +++ linux/fs/ext2/namei.c Wed May 25 08:46:40 1994 @@ -630,8 +630,9 @@ schedule(); goto repeat; } - if ((dir->i_mode & S_ISVTX) && current->euid && - inode->i_uid != current->euid) + if ((dir->i_mode & S_ISVTX) && !suser() && + current->euid != inode->i_uid && + current->euid != dir->i_uid) goto end_rmdir; if (inode == dir) /* we may not delete ".", but "../dir" is ok */ goto end_rmdir; diff -u --recursive --new-file v1.1.14/linux/fs/ext2/super.c linux/fs/ext2/super.c --- v1.1.14/linux/fs/ext2/super.c Tue Apr 19 10:53:22 1994 +++ linux/fs/ext2/super.c Wed May 25 08:46:40 1994 @@ -410,8 +410,8 @@ brelse (bh); set_blocksize (dev, sb->s_blocksize); - logic_sb_block = sb_block / sb->s_blocksize; - offset = sb_block % sb->s_blocksize; + logic_sb_block = (sb_block*BLOCK_SIZE) / sb->s_blocksize; + offset = (sb_block*BLOCK_SIZE) % sb->s_blocksize; bh = bread (dev, logic_sb_block, sb->s_blocksize); if(!bh) return NULL; diff -u --recursive --new-file v1.1.14/linux/fs/minix/file.c linux/fs/minix/file.c --- v1.1.14/linux/fs/minix/file.c Tue Apr 19 10:53:23 1994 +++ linux/fs/minix/file.c Wed May 25 09:02:46 1994 @@ -201,16 +201,13 @@ printk("minix_file_write: mode = %07o\n",inode->i_mode); return -EINVAL; } -/* - * ok, append may not work when many processes are writing at the same time - * but so what. That way leads to madness anyway. - */ + down(&inode->i_sem); if (filp->f_flags & O_APPEND) pos = inode->i_size; else pos = filp->f_pos; written = 0; - while (writtenb_data; pos += c; - if (pos > inode->i_size) { - inode->i_size = pos; - inode->i_dirt = 1; - } written += c; memcpy_fromfs(p,buf,c); buf += c; @@ -243,6 +236,9 @@ mark_buffer_dirty(bh, 0); brelse(bh); } + if (pos > inode->i_size) + inode->i_size = pos; + up(&inode->i_sem); inode->i_mtime = inode->i_ctime = CURRENT_TIME; filp->f_pos = pos; inode->i_dirt = 1; diff -u --recursive --new-file v1.1.14/linux/fs/minix/namei.c linux/fs/minix/namei.c --- v1.1.14/linux/fs/minix/namei.c Sat May 7 14:54:07 1994 +++ linux/fs/minix/namei.c Wed May 25 08:46:40 1994 @@ -443,8 +443,9 @@ retval = -EPERM; if (!(inode = iget(dir->i_sb, de->inode))) goto end_rmdir; - if ((dir->i_mode & S_ISVTX) && current->euid && - inode->i_uid != current->euid) + if ((dir->i_mode & S_ISVTX) && !suser() && + current->euid != inode->i_uid && + current->euid != dir->i_uid) goto end_rmdir; if (inode->i_dev != dir->i_dev) goto end_rmdir; diff -u --recursive --new-file v1.1.14/linux/fs/sysv/namei.c linux/fs/sysv/namei.c --- v1.1.14/linux/fs/sysv/namei.c Sat May 7 14:54:11 1994 +++ linux/fs/sysv/namei.c Wed May 25 08:46:40 1994 @@ -447,8 +447,9 @@ retval = -EPERM; if (!(inode = iget(dir->i_sb, de->inode))) goto end_rmdir; - if ((dir->i_mode & S_ISVTX) && current->euid && - inode->i_uid != current->euid) + if ((dir->i_mode & S_ISVTX) && !suser() && + current->euid != inode->i_uid && + current->euid != dir->i_uid) goto end_rmdir; if (inode->i_dev != dir->i_dev) goto end_rmdir; diff -u --recursive --new-file v1.1.14/linux/fs/xiafs/namei.c linux/fs/xiafs/namei.c --- v1.1.14/linux/fs/xiafs/namei.c Sat May 7 14:54:12 1994 +++ linux/fs/xiafs/namei.c Wed May 25 08:46:40 1994 @@ -496,8 +496,9 @@ retval = -EPERM; if (!(inode = iget(dir->i_sb, de->d_ino))) goto end_rmdir; - if ((dir->i_mode & S_ISVTX) && current->euid && - inode->i_uid != current->euid) + if ((dir->i_mode & S_ISVTX) && !suser() && + current->euid != inode->i_uid && + current->euid != dir->i_uid) goto end_rmdir; if (inode->i_dev != dir->i_dev) goto end_rmdir; diff -u --recursive --new-file v1.1.14/linux/ibcs/Makefile linux/ibcs/Makefile --- v1.1.14/linux/ibcs/Makefile Wed Dec 1 14:44:15 1993 +++ linux/ibcs/Makefile Wed May 25 11:24:50 1994 @@ -36,4 +36,3 @@ ifeq (.depend,$(wildcard .depend)) include .depend endif - diff -u --recursive --new-file v1.1.14/linux/ibcs/emulate.c linux/ibcs/emulate.c --- v1.1.14/linux/ibcs/emulate.c Tue Jan 25 09:37:08 1994 +++ linux/ibcs/emulate.c Wed May 25 11:26:10 1994 @@ -5,23 +5,6 @@ */ /* - * Emulate.c contains the entry point for the 'lcall 7,xxx' handler. + * Yes, sir, this file is completely empty, waiting for some real code.. + * I still copyright it, silly me. */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -asmlinkage void iABI_emulate(struct pt_regs * regs) -{ - printk("iBCS2 binaries not supported yet\n"); - do_exit(SIGSEGV); -} diff -u --recursive --new-file v1.1.14/linux/include/linux/sched.h linux/include/linux/sched.h --- v1.1.14/linux/include/linux/sched.h Tue May 24 08:47:07 1994 +++ linux/include/linux/sched.h Wed May 25 12:36:40 1994 @@ -89,6 +89,7 @@ #include #include #include +#include #define TASK_RUNNING 0 #define TASK_INTERRUPTIBLE 1 @@ -251,6 +252,7 @@ unsigned long flags; /* per process flags, defined below */ int errno; int debugreg[8]; /* Hardware debugging registers */ + asmlinkage void (*lcall7)(struct pt_regs *); /* various fields */ struct task_struct *next_task, *prev_task; struct sigaction sigaction[32]; @@ -324,6 +326,7 @@ #define INIT_TASK \ /* state etc */ { 0,15,15,0,0,0,0, \ /* debugregs */ { 0, }, \ +/* lcall 7 */ no_lcall7, \ /* schedlink */ &init_task,&init_task, \ /* signals */ {{ 0, },}, ident_map, ident_map, \ /* stack */ 0,(unsigned long) &init_kernel_stack, \ @@ -357,6 +360,9 @@ extern unsigned long itimer_next; extern struct timeval xtime; extern int need_resched; + +extern unsigned long ident_map[33]; +extern asmlinkage void no_lcall7(struct pt_regs *); #define CURRENT_TIME (xtime.tv_sec) diff -u --recursive --new-file v1.1.14/linux/include/linux/string.h linux/include/linux/string.h --- v1.1.14/linux/include/linux/string.h Tue Apr 5 07:37:24 1994 +++ linux/include/linux/string.h Tue May 24 08:33:03 1994 @@ -99,11 +99,10 @@ "jne 1b\n\t" "xorl %%eax,%%eax\n\t" "jmp 3f\n" - "2:\tmovl $1,%%eax\n\t" - "jb 3f\n\t" - "negl %%eax\n" + "2:\tsbbl %%eax,%%eax\n\t" + "orb $1,%%eax\n" "3:" - :"=a" (__res):"D" (cs),"S" (ct):"si","di"); + :"=a" (__res):"S" (cs),"D" (ct):"si","di"); return __res; } @@ -120,11 +119,10 @@ "jne 1b\n" "2:\txorl %%eax,%%eax\n\t" "jmp 4f\n" - "3:\tmovl $1,%%eax\n\t" - "jb 4f\n\t" - "negl %%eax\n" + "3:\tsbbl %%eax,%%eax\n\t" + "orb $1,%%al\n" "4:" - :"=a" (__res):"D" (cs),"S" (ct),"c" (count):"si","di","cx"); + :"=a" (__res):"S" (cs),"D" (ct),"c" (count):"si","di","cx"); return __res; } @@ -153,8 +151,7 @@ "1:\tlodsb\n\t" "cmpb %%ah,%%al\n\t" "jne 2f\n\t" - "movl %%esi,%0\n\t" - "decl %0\n" + "leal -1(%%esi),%0\n" "2:\ttestb %%al,%%al\n\t" "jne 1b" :"=d" (__res):"0" (0),"S" (s),"a" (c):"ax","si"); @@ -384,11 +381,10 @@ "repe\n\t" "cmpsb\n\t" "je 1f\n\t" - "movl $1,%%eax\n\t" - "jb 1f\n\t" - "negl %%eax\n" + "sbbl %%eax,%%eax\n\t" + "orb $1,%%al\n" "1:" - :"=a" (__res):"0" (0),"D" (cs),"S" (ct),"c" (count) + :"=a" (__res):"0" (0),"S" (cs),"D" (ct),"c" (count) :"si","di","cx"); return __res; } diff -u --recursive --new-file v1.1.14/linux/kernel/exit.c linux/kernel/exit.c --- v1.1.14/linux/kernel/exit.c Tue May 24 08:47:07 1994 +++ linux/kernel/exit.c Tue May 24 08:53:30 1994 @@ -282,12 +282,10 @@ * POSIX specifies that kill(-1,sig) is unspecified, but what we have * is probably wrong. Should make it like BSD or SYSV. */ -asmlinkage int sys_kill(int pid, unsigned int sig) +asmlinkage int sys_kill(int pid,int sig) { int err, retval = 0, count = 0; - if (sig > 32) - return -EINVAL; if (!pid) return(kill_pg(current->pgrp,sig,0)); if (pid == -1) { diff -u --recursive --new-file v1.1.14/linux/kernel/sched.c linux/kernel/sched.c --- v1.1.14/linux/kernel/sched.c Tue May 24 08:47:08 1994 +++ linux/kernel/sched.c Wed May 25 10:56:27 1994 @@ -87,16 +87,6 @@ extern int timer_interrupt(void); asmlinkage int system_call(void); -/* - * signal mapping: this is the default identity mapping used for normal - * linux binaries (it's both the reverse and the normal map, of course) - */ -static unsigned long ident_map[33] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, - 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, - 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 -}; - static unsigned long init_kernel_stack[1024] = { STACK_MAGIC, }; struct task_struct init_task = INIT_TASK; diff -u --recursive --new-file v1.1.14/linux/kernel/sys_call.S linux/kernel/sys_call.S --- v1.1.14/linux/kernel/sys_call.S Sat May 7 14:54:16 1994 +++ linux/kernel/sys_call.S Wed May 25 13:19:26 1994 @@ -78,6 +78,7 @@ errno = 24 dbgreg6 = 52 dbgreg7 = 56 +lcall7 = 60 ENOSYS = 38 @@ -141,8 +142,10 @@ movl %edx,EIP(%esp) # Now we move them to their "normal" places movl %ecx,CS(%esp) # movl %esp,%eax + movl _current,%edx pushl %eax - call _iABI_emulate + movl lcall7(%edx),%edx + call *%edx popl %eax jmp ret_from_sys_call diff -u --recursive --new-file v1.1.14/linux/net/inet/ip.c linux/net/inet/ip.c --- v1.1.14/linux/net/inet/ip.c Tue May 24 00:35:02 1994 +++ linux/net/inet/ip.c Wed May 25 16:27:36 1994 @@ -1264,7 +1264,7 @@ return; } - if(memcmp(skb->data,dev->broadcast, dev->addr_len)) + if(!memcmp(skb->data,dev->broadcast, dev->addr_len)) return;