diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-06-01 03:16:17 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1997-06-01 03:16:17 +0000 |
commit | d8d9b8f76f22b7a16a83e261e64f89ee611f49df (patch) | |
tree | 3067bc130b80d52808e6390c9fc7fc087ec1e33c /drivers/scsi/eata.c | |
parent | 19c9bba94152148523ba0f7ef7cffe3d45656b11 (diff) |
Initial revision
Diffstat (limited to 'drivers/scsi/eata.c')
-rw-r--r-- | drivers/scsi/eata.c | 94 |
1 files changed, 61 insertions, 33 deletions
diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c index fb82d349a..cfff8bfa3 100644 --- a/drivers/scsi/eata.c +++ b/drivers/scsi/eata.c @@ -1,6 +1,13 @@ /* * eata.c - Low-level driver for EATA/DMA SCSI host adapters. * + * 17 May 1997 rev. 3.10 for linux 2.0.30 and 2.1.38 + * Use of serial_number_at_timeout in abort and reset processing. + * Use of the __initfunc and __initdata macro in setup code. + * Minor cleanups in the list_statistics code. + * Increased controller busy timeout in order to better support + * slow SCSI devices. + * * 24 Feb 1997 rev. 3.00 for linux 2.0.29 and 2.1.26 * When loading as a module, parameter passing is now supported * both in 2.0 and in 2.1 style. @@ -202,8 +209,7 @@ * lc:n disables linked commands; * tc:y enables tagged commands; * tc:n disables tagged commands; - * tm:0 use head/simple/ordered queue tag sequences for reads and ordered - * queue tags for writes; + * tm:0 use head/simple/ordered queue tag sequences; * tm:1 use only simple queue tags; * tm:2 use only head of queue tags; * tm:3 use only ordered queue tags; @@ -232,10 +238,12 @@ * between increasing or decreasing by minimizing the seek distance between * the sector of the commands just completed and the sector of the first * command in the list to be sorted. - * Trivial math assures that if there are (Q-1) outstanding request for - * random seeks over S sectors, the unsorted average seek distance is S/2, - * while the sorted average seek distance is S/(Q-1). The seek distance is - * hence divided by a factor (Q-1)/2. + * Trivial math assures that the unsorted average seek distance when doing + * random seeks over S sectors is S/3. + * When (Q-1) requests are uniformly distributed over S sectors, the average + * distance between two adjacent requests is S/((Q-1) + 1), so the sorted + * average seek distance for (Q-1) random requests over S sectors is S/Q. + * The elevator sorting hence divides the seek distance by a factor Q/3. * The above pure geometric remarks are valid in all cases and the * driver effectively reduces the seek distance by the predicted factor * when there are Q concurrent read i/o operations on the device, but this @@ -286,10 +294,18 @@ MODULE_AUTHOR("Dario Ballabio"); #include <asm/dma.h> #include <asm/irq.h> #include "eata.h" -#include<linux/stat.h> -#include<linux/config.h> -#include<linux/bios32.h> -#include<linux/pci.h> +#include <linux/stat.h> +#include <linux/config.h> +#include <linux/bios32.h> +#include <linux/pci.h> + +#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,36) +#include <linux/init.h> +#else +#define __initfunc(A) A +#define __initdata +#define __init +#endif struct proc_dir_entry proc_scsi_eata2x = { PROC_SCSI_EATA2X, 6, "eata2x", @@ -517,7 +533,7 @@ static struct Scsi_Host *sh[MAX_BOARDS + 1]; static const char *driver_name = "EATA"; static unsigned int irqlist[MAX_IRQ], calls[MAX_IRQ]; -static unsigned int io_port[] = { +static unsigned int io_port[] __initdata = { /* Space for MAX_INT_PARAM ports usable while loading as a module */ SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, @@ -638,8 +654,7 @@ static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) { return; } -static inline int wait_on_busy(unsigned int iobase) { - unsigned int loop = MAXLOOP; +static inline int wait_on_busy(unsigned int iobase, unsigned int loop) { while (inb(iobase + REG_AUX_STATUS) & ABSY_ASSERTED) if (--loop == 0) return TRUE; @@ -649,7 +664,7 @@ static inline int wait_on_busy(unsigned int iobase) { static inline int do_dma(unsigned int iobase, unsigned int addr, unchar cmd) { - if (wait_on_busy(iobase)) return TRUE; + if (wait_on_busy(iobase, (addr ? MAXLOOP * 100 : MAXLOOP))) return TRUE; if ((addr = V2DEV(addr))) { outb((char) (addr >> 24), iobase + REG_LOW); @@ -678,8 +693,8 @@ static inline int read_pio(unsigned int iobase, ushort *start, ushort *end) { return FALSE; } -static inline int port_detect(unsigned int port_base, unsigned int j, - Scsi_Host_Template *tpnt) { +__initfunc (static inline int port_detect \ + (unsigned int port_base, unsigned int j, Scsi_Host_Template *tpnt)) { unsigned char irq, dma_channel, subversion, i; unsigned char protocol_rev; struct eata_info info; @@ -882,7 +897,7 @@ static inline int port_detect(unsigned int port_base, unsigned int j, sh[j]->max_lun = info.max_lun + 1; } - if (dma_channel == NO_DMA) sprintf(dma_name, "%s", "NO DMA"); + if (dma_channel == NO_DMA) sprintf(dma_name, "%s", "BMST"); else sprintf(dma_name, "DMA %u", dma_channel); for (i = 0; i < sh[j]->can_queue; i++) @@ -941,7 +956,7 @@ static inline int port_detect(unsigned int port_base, unsigned int j, return TRUE; } -void eata2x_setup(char *str, int *ints) { +__initfunc (void eata2x_setup(char *str, int *ints)) { int i, argc = ints[0]; char *cur = str, *pc; @@ -974,7 +989,7 @@ void eata2x_setup(char *str, int *ints) { return; } -static void add_pci_ports(void) { +__initfunc (static void add_pci_ports(void)) { #if defined(CONFIG_PCI) @@ -1009,7 +1024,7 @@ static void add_pci_ports(void) { return; } -int eata2x_detect(Scsi_Host_Template *tpnt) { +__initfunc (int eata2x_detect(Scsi_Host_Template *tpnt)) { unsigned long flags; unsigned int j = 0, k; @@ -1166,6 +1181,9 @@ int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { cpp->reqsen = TRUE; cpp->dispri = TRUE; +#if 0 + if (SCpnt->device->type == TYPE_TAPE) cpp->hbaci = TRUE; +#endif cpp->one = TRUE; cpp->channel = SCpnt->channel; cpp->target = SCpnt->target; @@ -1182,14 +1200,12 @@ int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { else if (tag_mode == TAG_SIMPLE) cpp->mess[0] = SIMPLE_QUEUE_TAG; else if (tag_mode == TAG_HEAD) cpp->mess[0] = HEAD_OF_QUEUE_TAG; else if (tag_mode == TAG_ORDERED) cpp->mess[0] = ORDERED_QUEUE_TAG; - else if ((SCpnt->device->current_tag % SCpnt->device->queue_depth) == 0) + else if (SCpnt->device->current_tag == 0) cpp->mess[0] = ORDERED_QUEUE_TAG; - else if ((SCpnt->device->current_tag % SCpnt->device->queue_depth) == 1) + else if (SCpnt->device->current_tag == 1) cpp->mess[0] = HEAD_OF_QUEUE_TAG; - else if (cpp->din) - cpp->mess[0] = SIMPLE_QUEUE_TAG; else - cpp->mess[0] = ORDERED_QUEUE_TAG; + cpp->mess[0] = SIMPLE_QUEUE_TAG; cpp->mess[1] = SCpnt->device->current_tag++; } @@ -1208,7 +1224,7 @@ int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { if (linked_comm && SCpnt->device->queue_depth > 2 && TLDEV(SCpnt->device->type)) { HD(j)->cp_stat[i] = READY; - flush_dev(SCpnt->device, 0, j, FALSE); + flush_dev(SCpnt->device, SCpnt->request.sector, j, FALSE); restore_flags(flags); return 0; } @@ -1238,7 +1254,8 @@ int eata2x_abort(Scsi_Cmnd *SCarg) { cli(); j = ((struct hostdata *) SCarg->host->hostdata)->board_number; - if (SCarg->host_scribble == NULL) { + if (SCarg->host_scribble == NULL + || SCarg->serial_number != SCarg->serial_number_at_timeout) { printk("%s: abort, target %d.%d:%d, pid %ld inactive.\n", BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); restore_flags(flags); @@ -1252,7 +1269,7 @@ int eata2x_abort(Scsi_Cmnd *SCarg) { if (i >= sh[j]->can_queue) panic("%s: abort, invalid SCarg->host_scribble.\n", BN(j)); - if (wait_on_busy(sh[j]->io_port)) { + if (wait_on_busy(sh[j]->io_port, MAXLOOP)) { printk("%s: abort, timeout error.\n", BN(j)); restore_flags(flags); return SCSI_ABORT_ERROR; @@ -1321,13 +1338,19 @@ int eata2x_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) { if (SCarg->host_scribble == NULL) printk("%s: reset, pid %ld inactive.\n", BN(j), SCarg->pid); + if (SCarg->serial_number != SCarg->serial_number_at_timeout) { + printk("%s: reset, pid %ld, reset not running.\n", BN(j), SCarg->pid); + restore_flags(flags); + return SCSI_RESET_NOT_RUNNING; + } + if (HD(j)->in_reset) { printk("%s: reset, exit, already in reset.\n", BN(j)); restore_flags(flags); return SCSI_RESET_ERROR; } - if (wait_on_busy(sh[j]->io_port)) { + if (wait_on_busy(sh[j]->io_port, MAXLOOP)) { printk("%s: reset, exit, timeout error.\n", BN(j)); restore_flags(flags); return SCSI_RESET_ERROR; @@ -1480,7 +1503,7 @@ static inline void reorder(unsigned int j, unsigned long cursec, unsigned int rev = FALSE, s = TRUE, r = TRUE; unsigned int input_only = TRUE, overlap = FALSE; unsigned long sl[n_ready], pl[n_ready], ll[n_ready]; - unsigned long maxsec = 0, minsec = ULONG_MAX, seek = 0; + unsigned long maxsec = 0, minsec = ULONG_MAX, seek = 0, iseek = 0; static unsigned int flushcount = 0, batchcount = 0, sortcount = 0; static unsigned int readycount = 0, ovlcount = 0, inputcount = 0; @@ -1491,8 +1514,8 @@ static inline void reorder(unsigned int j, unsigned long cursec, printk("fc %d bc %d ic %d oc %d rc %d rs %d sc %d re %d"\ " av %ldK as %ldK.\n", flushcount, batchcount, inputcount, ovlcount, readycount, readysorted, sortcount, revcount, - seeknosort / (readycount - batchcount + 1), - seeksorted / (readycount - batchcount + 1)); + seeknosort / (readycount + 1), + seeksorted / (readycount + 1)); if (n_ready <= 1) return; @@ -1520,6 +1543,10 @@ static inline void reorder(unsigned int j, unsigned long cursec, } + if (link_statistics) { + if (cursec > sl[0]) seek += cursec - sl[0]; else seek += sl[0] - cursec; + } + if (cursec > ((maxsec + minsec) / 2)) rev = TRUE; if (!((rev && r) || (!rev && s))) sort(sl, il, n_ready, rev); @@ -1537,10 +1564,11 @@ static inline void reorder(unsigned int j, unsigned long cursec, if (overlap) sort(pl, il, n_ready, FALSE); if (link_statistics) { + if (cursec > sl[0]) iseek = cursec - sl[0]; else iseek = sl[0] - cursec; batchcount++; readycount += n_ready, seeknosort += seek / 1024; if (input_only) inputcount++; if (overlap) { ovlcount++; seeksorted += seek / 1024; } - else seeksorted += (maxsec - minsec) / 1024; + else seeksorted += (iseek + maxsec - minsec) / 1024; if (rev && !r) { revcount++; readysorted += n_ready; } if (!rev && !s) { sortcount++; readysorted += n_ready; } } |