Re: 2.0.2[79]: aha1740 still doesn't work as module

Andreas Degert (ad@papyrus.hamburg.com)
16 Feb 1997 18:59:12 +0100


Hello,

i have a patch that works for me, but it isn't tested by anyone else
yet. 2 Patches are appended at the end of the mail, for 2.0.29 and for
2.1.26.

I'm not an expert on linux device drivers, so i'll explain what i did,
maybe someone else can check it:

The scsi-card is accessing the elements of the array ecb (declared
static) via dma (it is given the physical address of these
elements). When the driver is compiled into the kernel, the array
seems to be contiguous in physical memory. When the driver is loaded
as a module, it's loaded into virtual memory, so the array won't
always be contiguous in physical memory.

I changed a static struct ecb[] to a pointer, and allocated the memory
with scsi_init_malloc(...,GFP_ATOMIC), in order to reserve a
contiguous block of memory.

I'm not sure why the driver is failing without this change. The
controller is given the physical address of the beginning of the
array-element, so maybe there is a page border crossing the element,
and the rest of the fields (of struct ebc) is at another location than
the controller assumes.

The other changes: I defined a release-function, changed the elements
of the reset-function to match the prototype (for 2.0.29), and changed
the management of resources like in other scsi-drivers. I had to do
these changes so the driver can be unloaded (and even loaded again...).

If someone wants to use more than one host adapter, I think the
pointer for ecb must be moved to the private data for the host
(hostdata in struct Scsi_Host). I can't test it, so i didn't make that
change.

ciao
----------------------------------------------------

Klaus Kudielka <oe1kib@oe1xtu.ampr.org> writes:

> I just wanted to upgrade my machine to Red Hat 4.1 (bootdisk has
> 2.0.27), but discovered that the Adaptec 1740 driver still does not work
> correctly as a module. When insmod'ed, it detects seven disks (id 0 to
> id 7) with bogus (i.e. null) device information, although there is only
> one disk present (id 0). Even on disk 0 there are no partitions detected
> (although they are here -- Red Hat 4.0 runs quite nicely with 2.0.27 and
> the compiled-in driver).
> The module _is_ inserted, it just doesn't work as it should.
> The same happens for a custom 2.0.29 kernel.
>
> Remember, for Red Hat 4.0 there were special boot disks with SCSI
> drivers compiled into the kernel.
> Some drivers (e.g. the ncr53c8xx) seem to have been fixed for this
> problem.
> The 1740 driver definitely hasn't been fixed :-(
>
> Questioins/Suggestions:
> (1) Does anybody know a fix?
> (2) If not, it should not be allowed to compile the driver as a module.
>

----------- patch for 2.0.29 ---------------------------------
diff -u --recursive linux-2.0.29/drivers/scsi/aha1740.c linux/drivers/scsi/aha1740.c
--- linux-2.0.29/drivers/scsi/aha1740.c Thu May 2 10:32:00 1996
+++ linux/drivers/scsi/aha1740.c Fri Nov 22 21:49:07 1996
@@ -62,7 +62,7 @@
static unsigned int slot, base;
static unsigned char irq_level;

-static struct ecb ecb[AHA1740_ECBS]; /* One for each queued operation */
+static struct ecb* ecb; /* One for each queued operation */

static int aha1740_last_ecb_used = 0; /* optimization */

@@ -440,9 +440,10 @@

int aha1740_detect(Scsi_Host_Template * tpnt)
{
+ struct Scsi_Host* sh;
+
tpnt->proc_dir = &proc_scsi_aha1740;

- memset(&ecb, 0, sizeof(struct ecb));
DEB(printk("aha1740_detect: \n"));

for ( slot=MINEISA; slot <= MAXEISA; slot++ )
@@ -470,17 +471,37 @@
printk("Configuring Adaptec at IO:%x, IRQ %d\n",base,
irq_level);

+ ecb = (struct ecb*)scsi_init_malloc(AHA1740_ECBS*sizeof(struct ecb),
+ GFP_ATOMIC);
+ if (!ecb)
+ {
+ printk("Unable to allocate memory for ECB's (AHA1740)\n");
+ return 0;
+ }
+ memset(ecb, 0, sizeof(struct ecb));
DEB(printk("aha1740_detect: enable interrupt channel %d\n", irq_level));
-
if (request_irq(irq_level,aha1740_intr_handle, 0, "aha1740", NULL))
{
printk("Unable to allocate IRQ for adaptec controller.\n");
+ scsi_init_free((char*)ecb,AHA1740_ECBS*sizeof(struct ecb));
return 0;
}
request_region(base, 0x5c,"aha1740"); /* Reserve the space that we need to use */
+ sh = scsi_register(tpnt,0);
+ sh->irq = irq_level;
+ sh->io_port = base;
+ sh->n_io_port = 0x5c;
return 1;
}

+int aha1740_release(struct Scsi_Host *sh)
+{
+if (sh->irq) free_irq(sh->irq,NULL);
+if (sh->io_port && sh->n_io_port) release_region(sh->io_port,sh->n_io_port);
+if (ecb) scsi_init_free((char*)ecb,AHA1740_ECBS*sizeof(struct ecb));
+return 0;
+}
+
/* Note: They following two functions do not apply very well to the Adaptec,
which basically manages its own affairs quite well without our interference,
so I haven't put anything into them. I can faintly imagine someone with a
@@ -499,7 +520,7 @@
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 aha1740_reset(Scsi_Cmnd * SCpnt)
+int aha1740_reset(Scsi_Cmnd * SCpnt, unsigned int ResetFlags)
{
DEB(printk("aha1740_reset called\n"));
return SCSI_RESET_PUNT;
diff -u --recursive linux-2.0.29/drivers/scsi/aha1740.h linux/drivers/scsi/aha1740.h
--- linux-2.0.29/drivers/scsi/aha1740.h Thu Sep 21 08:01:48 1995
+++ linux/drivers/scsi/aha1740.h Sun Nov 24 00:33:59 1996
@@ -154,10 +154,11 @@
#define AHA1740CMD_TARG 0x10 /* Target SCSI Command */

int aha1740_detect(Scsi_Host_Template *);
+int aha1740_release(struct Scsi_Host *);
int aha1740_command(Scsi_Cmnd *);
int aha1740_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
int aha1740_abort(Scsi_Cmnd *);
-int aha1740_reset(Scsi_Cmnd *);
+int aha1740_reset(Scsi_Cmnd *, unsigned int);
int aha1740_biosparam(Disk *, kdev_t, int*);

#define AHA1740_ECBS 32
@@ -173,7 +174,7 @@
NULL, \
"Adaptec 174x (EISA)", \
aha1740_detect, \
- NULL, \
+ aha1740_release, \
NULL, \
aha1740_command, \
aha1740_queuecommand, \

----------- patch for 2.1.26 ---------------------------------
diff -u --recursive linux-2.1.26/drivers/scsi/aha1740.c linux/drivers/scsi/aha1740.c
--- linux-2.1.26/drivers/scsi/aha1740.c Sun Feb 16 17:42:55 1997
+++ linux/drivers/scsi/aha1740.c Mon Dec 30 11:17:51 1996
@@ -62,7 +62,7 @@
static unsigned int slot, base;
static unsigned char irq_level;

-static struct ecb ecb[AHA1740_ECBS]; /* One for each queued operation */
+static struct ecb* ecb; /* One for each queued operation */

static int aha1740_last_ecb_used = 0; /* optimization */

@@ -440,9 +440,10 @@

int aha1740_detect(Scsi_Host_Template * tpnt)
{
+ struct Scsi_Host* sh;
+
tpnt->proc_dir = &proc_scsi_aha1740;

- memset(&ecb, 0, sizeof(struct ecb));
DEB(printk("aha1740_detect: \n"));

for ( slot=MINEISA; slot <= MAXEISA; slot++ )
@@ -470,15 +471,35 @@
printk("Configuring Adaptec at IO:%x, IRQ %d\n",base,
irq_level);

+ ecb = (struct ecb*)scsi_init_malloc(AHA1740_ECBS*sizeof(struct ecb),
+ GFP_ATOMIC);
+ if (!ecb)
+ {
+ printk("Unable to allocate memory for ECB's (AHA1740)\n");
+ return 0;
+ }
+ memset(ecb, 0, sizeof(struct ecb));
DEB(printk("aha1740_detect: enable interrupt channel %d\n", irq_level));
-
if (request_irq(irq_level,aha1740_intr_handle, 0, "aha1740", NULL))
{
printk("Unable to allocate IRQ for adaptec controller.\n");
+ scsi_init_free((char*)ecb,AHA1740_ECBS*sizeof(struct ecb));
return 0;
}
request_region(base, 0x5c,"aha1740"); /* Reserve the space that we need to use */
+ sh = scsi_register(tpnt,0);
+ sh->irq = irq_level;
+ sh->io_port = base;
+ sh->n_io_port = 0x5c;
return 1;
+}
+
+int aha1740_release(struct Scsi_Host *sh)
+{
+if (sh->irq) free_irq(sh->irq,NULL);
+if (sh->io_port && sh->n_io_port) release_region(sh->io_port,sh->n_io_port);
+if (ecb) scsi_init_free((char*)ecb,AHA1740_ECBS*sizeof(struct ecb));
+return 0;
}

/* Note: They following two functions do not apply very well to the Adaptec,
diff -u --recursive linux-2.1.26/drivers/scsi/aha1740.h linux/drivers/scsi/aha1740.h
--- linux-2.1.26/drivers/scsi/aha1740.h Sun Feb 16 17:42:55 1997
+++ linux/drivers/scsi/aha1740.h Sat Nov 23 17:37:20 1996
@@ -154,6 +154,7 @@
#define AHA1740CMD_TARG 0x10 /* Target SCSI Command */

int aha1740_detect(Scsi_Host_Template *);
+int aha1740_release(struct Scsi_Host *);
int aha1740_command(Scsi_Cmnd *);
int aha1740_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
int aha1740_abort(Scsi_Cmnd *);
@@ -173,7 +174,7 @@
NULL, \
"Adaptec 174x (EISA)", \
aha1740_detect, \
- NULL, \
+ aha1740_release, \
NULL, \
aha1740_command, \
aha1740_queuecommand, \