patch-2.2.18 linux/drivers/scsi/atp870u.c
Next file: linux/drivers/scsi/atp870u.h
Previous file: linux/drivers/scsi/atari_scsi.c
Back to the patch index
Back to the overall index
- Lines: 714
- Date:
Thu Aug 31 15:07:52 2000
- Orig file:
v2.2.17/drivers/scsi/atp870u.c
- Orig date:
Fri Apr 21 12:46:28 2000
diff -u --new-file --recursive --exclude-from /usr/src/exclude v2.2.17/drivers/scsi/atp870u.c linux/drivers/scsi/atp870u.c
@@ -1,11 +1,15 @@
/* $Id: atp870u.c,v 1.0 1997/05/07 15:22:00 root Exp root $
* linux/kernel/atp870u.c
*
- * Copyright (C) 1997 Wu Ching Chen
+ * Copyright (C) 1997 Wu Ching Chen
* 2.1.x update (C) 1998 Krzysztof G. Baranowski
- *
- * Marcelo Tosatti <marcelo@conectiva.com.br> : SMP fixes
- *
+ *
+ * Marcelo Tosatti <marcelo@conectiva.com.br> : SMP fixes
+ *
+ * Wu Ching Chen : NULL pointer fixes 2000/06/02
+ * support atp876 chip
+ * enable 32 bit fifo transfer
+ * support cdrom & remove device run ultra speed
*/
#include <linux/module.h>
@@ -106,19 +110,19 @@
dev->in_int = 1;
workportu = dev->ioport;
tmport = workportu;
-
- if (dev->working != 0)
+
+ if (dev->working != 0)
{
tmport += 0x1f;
j = inb(tmport);
- if((j&0x80)==0)
+ if ((j & 0x80) == 0)
{
- dev->in_int=0;
+ dev->in_int = 0;
return;
}
tmpcip = dev->pciport;
- if ((inb(tmpcip) & 0x08) != 0)
+ if ((inb(tmpcip) & 0x08) != 0)
{
tmpcip += 0x2;
for (k=0; k < 1000; k++)
@@ -130,7 +134,7 @@
if ((inb(tmpcip) & 0x01) == 0)
{
goto stop_dma;
- }
+ }
}
}
stop_dma:
@@ -139,9 +143,9 @@
tmport -= 0x08;
i = inb(tmport);
- if ((j & 0x40) == 0)
+ if ((j & 0x40) == 0)
{
- if ((dev->last_cmd & 0x40) == 0)
+ if ((dev->last_cmd & 0x40) == 0)
{
dev->last_cmd = 0xff;
}
@@ -155,30 +159,32 @@
/*
* Remap wide devices onto id numbers
*/
-
+
if ((target_id & 0x40) != 0) {
target_id = (target_id & 0x07) | 0x08;
} else {
target_id &= 0x07;
}
-
- if (i == 0x85)
+
+ if (i == 0x85)
{
/*
* Flip wide
*/
- if (dev->wide_idu != 0)
+ if (dev->wide_idu != 0)
{
tmport = workportu + 0x1b;
- j = inb(tmport) & 0x0e;
- j |= 0x01;
- outb(j, tmport);
+ outb(0x01,tmport);
+ while ((inb(tmport) & 0x01) != 0x01)
+ {
+ outb(0x01,tmport);
+ }
}
/*
* Issue more commands
*/
if (((dev->quhdu != dev->quendu) || (dev->last_cmd != 0xff)) &&
- (dev->in_snd == 0))
+ (dev->in_snd == 0))
{
send_s870(h);
}
@@ -188,7 +194,7 @@
dev->in_int = 0;
return;
}
- if (i == 0x21)
+ if (i == 0x21)
{
tmport -= 0x05;
adrcntu = 0;
@@ -206,7 +212,7 @@
dev->in_int = 0;
return;
}
- if ((i == 0x80) || (i == 0x8f))
+ if ((i == 0x80) || (i == 0x8f))
{
lun = 0;
tmport -= 0x07;
@@ -215,7 +221,7 @@
tmport += 0x0d;
lun = inb(tmport) & 0x07;
} else {
- if (j == 0x41)
+ if (j == 0x41)
{
tmport += 0x02;
adrcntu = 0;
@@ -231,7 +237,7 @@
dev->in_int = 0;
return;
}
- else
+ else
{
outb(0x46, tmport);
dev->id[target_id].dirctu = 0x00;
@@ -252,7 +258,7 @@
/*
* Remap wide identifiers
*/
- if ((target_id & 0x10) != 0)
+ if ((target_id & 0x10) != 0)
{
target_id = (target_id & 0x07) | 0x08;
} else {
@@ -277,8 +283,21 @@
j |= dev->id[target_id].dirctu;
outb(j, tmport++);
outb(0x80, tmport);
+
+ /* enable 32 bit fifo transfer */
+ tmport = workportu + 0x3a;
+ if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) ||
+ (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a))
+ {
+ outb((unsigned char)((inb(tmport) & 0xf3) | 0x08),tmport);
+ }
+ else
+ {
+ outb((unsigned char)(inb(tmport) & 0xf3),tmport);
+ }
+
tmport = workportu + 0x1b;
- j = inb(tmport) & 0x0e;
+ j = 0;
id = 1;
id = id << target_id;
/*
@@ -288,7 +307,11 @@
j |= 0x01;
}
outb(j, tmport);
-
+ while ((inb(tmport) & 0x01) != j)
+ {
+ outb(j,tmport);
+ }
+
if (dev->id[target_id].last_lenu == 0) {
tmport = workportu + 0x18;
outb(0x08, tmport);
@@ -296,7 +319,7 @@
return;
}
prd = dev->id[target_id].prd_posu;
- while (adrcntu != 0)
+ while (adrcntu != 0)
{
id = ((unsigned short int *) (prd))[2];
if (id == 0) {
@@ -340,19 +363,19 @@
dev->in_int = 0;
return;
}
-
+
/*
* Current scsi request on this target
*/
-
+
workrequ = dev->id[target_id].curr_req;
-
+
if (i == 0x42) {
errstus = 0x02;
workrequ->result = errstus;
goto go_42;
}
- if (i == 0x16)
+ if (i == 0x16)
{
errstus = 0;
tmport -= 0x08;
@@ -376,15 +399,17 @@
*/
if (dev->wide_idu != 0) {
tmport = workportu + 0x1b;
- j = inb(tmport) & 0x0e;
- j |= 0x01;
- outb(j, tmport);
+ outb(0x01,tmport);
+ while ((inb(tmport) & 0x01) != 0x01)
+ {
+ outb(0x01,tmport);
+ }
}
/*
* If there is stuff to send and nothing going then send it
*/
if (((dev->last_cmd != 0xff) || (dev->quhdu != dev->quendu)) &&
- (dev->in_snd == 0))
+ (dev->in_snd == 0))
{
send_s870(h);
}
@@ -445,9 +470,9 @@
dev->in_int = 0;
return;
} else {
- tmport = workportu + 0x17;
- inb(tmport);
- dev->working = 0;
+// tmport = workportu + 0x17;
+// inb(tmport);
+// dev->working = 0;
dev->in_int = 0;
return;
}
@@ -480,7 +505,7 @@
/*
* Fake a timeout for missing targets
*/
-
+
if ((m & dev->active_idu) == 0) {
req_p->result = 0x00040000;
done(req_p);
@@ -556,7 +581,17 @@
if ((dev->last_cmd != 0xff) && ((dev->last_cmd & 0x40) != 0)) {
dev->last_cmd &= 0x0f;
workrequ = dev->id[dev->last_cmd].curr_req;
- goto cmd_subp;
+ if (workrequ != NULL) /* check NULL pointer */
+ {
+ goto cmd_subp;
+ }
+ dev->last_cmd = 0xff;
+ if (dev->quhdu == dev->quendu)
+ {
+ dev->in_snd = 0;
+ restore_flags(flags);
+ return ;
+ }
}
dev->working++;
j = dev->quhdu;
@@ -597,6 +632,9 @@
workrequ->request_bufflen = 0x08;
}
}
+ if (dev->ata_cdbu[0] == 0x00) {
+ workrequ->request_bufflen = 0;
+ }
/*
* Why limit this ????
*/
@@ -606,11 +644,11 @@
dev->ata_cdbu[4] = 0x24;
}
}
-
+
tmport = workportu + 0x1b;
- j = inb(tmport) & 0x0e;
+ j = 0;
target_id = workrequ->target;
-
+
/*
* Wide ?
*/
@@ -618,13 +656,17 @@
w = w << target_id;
if ((w & dev->wide_idu) != 0) {
j |= 0x01;
- }
+ }
outb(j, tmport);
-
+ while ((inb(tmport) & 0x01) != j)
+ {
+ outb(j,tmport);
+ }
+
/*
* Write the command
*/
-
+
tmport = workportu;
outb(workrequ->cmd_len, tmport++);
outb(0x2c, tmport++);
@@ -639,17 +681,17 @@
* Write the target
*/
outb(dev->id[target_id].devspu, tmport++);
-
+
/*
* Figure out the transfer size
*/
- if (workrequ->use_sg)
+ if (workrequ->use_sg)
{
l = 0;
sgpnt = (struct scatterlist *) workrequ->request_buffer;
- for (i = 0; i < workrequ->use_sg; i++)
+ for (i = 0; i < workrequ->use_sg; i++)
{
- if (sgpnt[i].length == 0 || workrequ->use_sg > ATP870U_SCATTER)
+ if (sgpnt[i].length == 0 || workrequ->use_sg > ATP870U_SCATTER)
{
panic("Foooooooood fight!");
}
@@ -700,13 +742,13 @@
tmpcip = dev->pciport;
prd = dev->id[target_id].prd_tableu;
dev->id[target_id].prd_posu = prd;
-
+
/*
* Now write the request list. Either as scatter/gather or as
* a linear chain.
*/
-
- if (workrequ->use_sg)
+
+ if (workrequ->use_sg)
{
sgpnt = (struct scatterlist *) workrequ->request_buffer;
i = 0;
@@ -743,8 +785,21 @@
outb(0x06, tmpcip);
outb(0x00, tmpcip);
tmpcip = tmpcip - 2;
+
+ tmport = workportu + 0x3a;
+ if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) ||
+ (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a))
+ {
+ outb((unsigned char)((inb(tmport) & 0xf3) | 0x08),tmport);
+ }
+ else
+ {
+ outb((unsigned char)(inb(tmport) & 0xf3),tmport);
+ }
+ tmport = workportu + 0x1c;
+
if ((dev->ata_cdbu[0] == WRITE_6) || (dev->ata_cdbu[0] == WRITE_10) ||
- (dev->ata_cdbu[0] == WRITE_12) || (dev->ata_cdbu[0] == MODE_SELECT))
+ (dev->ata_cdbu[0] == WRITE_12) || (dev->ata_cdbu[0] == MODE_SELECT))
{
dev->id[target_id].dirctu = 0x20;
if (inb(tmport) == 0) {
@@ -758,7 +813,7 @@
restore_flags(flags);
return;
}
- if (inb(tmport) == 0)
+ if (inb(tmport) == 0)
{
tmport = workportu + 0x18;
outb(0x08, tmport);
@@ -804,20 +859,20 @@
goto FUN_D7;
}
}
- *val |= 0x4000; /* assert DB6 */
+ *val |= 0x4000; /* assert DB6 */
outw(*val, tmport);
- *val &= 0xdfff; /* assert DB5 */
+ *val &= 0xdfff; /* assert DB5 */
outw(*val, tmport);
FUN_D5:
for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */
- if ((inw(tmport) & 0x2000) != 0) { /* DB5 all release? */
+ if ((inw(tmport) & 0x2000) != 0) { /* DB5 all release? */
goto FUN_D5;
}
}
- *val |= 0x8000; /* no DB4-0, assert DB7 */
+ *val |= 0x8000; /* no DB4-0, assert DB7 */
*val &= 0xe0ff;
outw(*val, tmport);
- *val &= 0xbfff; /* release DB6 */
+ *val &= 0xbfff; /* release DB6 */
outw(*val, tmport);
FUN_D6:
for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */
@@ -893,9 +948,9 @@
outb(k, tmport++);
tmport = dev->ioport + 0x1b;
if (dev->chip_veru == 4) {
- outb((unsigned char) ((inb(tmport) & 0x0e) | 0x01), tmport);
+ outb(0x01, tmport);
} else {
- outb((unsigned char) (inb(tmport) & 0x0e), tmport);
+ outb(0x00, tmport);
}
wait_rdyok:
tmport = dev->ioport + 0x18;
@@ -923,17 +978,17 @@
outb(0, 0x80);
- val = 0x0080; /* bsy */
+ val = 0x0080; /* bsy */
tmport = dev->ioport + 0x1c;
outw(val, tmport);
- val |= 0x0040; /* sel */
+ val |= 0x0040; /* sel */
outw(val, tmport);
- val |= 0x0004; /* msg */
+ val |= 0x0004; /* msg */
outw(val, tmport);
inb(0x80); /* 2 deskew delay(45ns*2=90ns) */
val &= 0x007f; /* no bsy */
outw(val, tmport);
- mydlyu(0xffff); /* recommanded SCAM selection response time */
+ mydlyu(0xffff); /* recommanded SCAM selection response time */
mydlyu(0xffff);
val &= 0x00fb; /* after 1ms no msg */
outw(val, tmport);
@@ -983,7 +1038,7 @@
val |= 0x3f00;
fun_scam(dev, &val);
outb(3, 0x80);
- val &= 0x00ff; /* isolation */
+ val &= 0x00ff; /* isolation */
val |= 0x2000;
fun_scam(dev, &val);
outb(4, 0x80);
@@ -1018,10 +1073,10 @@
printk(" \n%x %x %x %s\n ",assignid_map,mbuf[0],mbuf[1],&mbuf[2]); */
i = 15;
j = mbuf[0];
- if ((j & 0x20) != 0) { /* bit5=1:ID upto 7 */
+ if ((j & 0x20) != 0) { /* bit5=1:ID upto 7 */
i = 7;
}
- if ((j & 0x06) == 0) { /* IDvalid? */
+ if ((j & 0x06) == 0) { /* IDvalid? */
goto G2Q5;
}
k = mbuf[1];
@@ -1036,7 +1091,7 @@
goto small_id;
}
G2Q5: /* srch from max acceptable ID# */
- k = i; /* max acceptable ID# */
+ k = i; /* max acceptable ID# */
G2Q_LP:
m = 1;
m <<= k;
@@ -1047,12 +1102,12 @@
k--;
goto G2Q_LP;
}
-G2Q_QUIN: /* k=binID#, */
+G2Q_QUIN: /* k=binID#, */
assignid_map |= m;
if (k < 8) {
quintet[0] = 0x38; /* 1st dft ID<8 */
} else {
- quintet[0] = 0x31; /* 1st ID>=8 */
+ quintet[0] = 0x31; /* 1st ID>=8 */
}
k &= 0x07;
quintet[1] = g2q_tab[k];
@@ -1073,15 +1128,15 @@
void is870(unsigned long host, unsigned int wkport)
{
unsigned int tmport;
- unsigned char i, j, k, rmb;
+ unsigned char i, j, k, rmb, n;
unsigned short int m;
static unsigned char mbuf[512];
- static unsigned char satn[9] = {0, 0, 0, 0, 0, 0, 0, 6, 6};
+ static unsigned char satn[9] = {0, 0, 0, 0, 0, 0, 0, 6, 6};
static unsigned char inqd[9] = {0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6};
- static unsigned char synn[6] = {0x80, 1, 3, 1, 0x19, 0x0e};
+ static unsigned char synn[6] = {0x80, 1, 3, 1, 0x19, 0x0e};
static unsigned char synu[6] = {0x80, 1, 3, 1, 0x0c, 0x0e};
static unsigned char synw[6] = {0x80, 1, 3, 1, 0x0c, 0x07};
- static unsigned char wide[6] = {0x80, 1, 2, 3, 1, 0};
+ static unsigned char wide[6] = {0x80, 1, 2, 3, 1, 0};
struct atp_unit *dev = &atp_unit[host];
sync_idu = 0;
@@ -1101,10 +1156,13 @@
printk(KERN_INFO " ID: %2d Host Adapter\n", dev->host_idu);
continue;
}
+ tmport = wkport + 0x1b;
if (dev->chip_veru == 4) {
- tmport = wkport + 0x1b;
- j = (inb(tmport) & 0x0e) | 0x01;
- outb(j, tmport);
+ outb(0x01, tmport);
+ }
+ else
+ {
+ outb(0x00, tmport);
}
tmport = wkport + 1;
outb(0x08, tmport++);
@@ -1180,10 +1238,9 @@
continue;
}
while (inb(tmport) != 0x8e);
+ tmport = wkport + 0x1b;
if (dev->chip_veru == 4) {
- tmport = wkport + 0x1b;
- j = inb(tmport) & 0x0e;
- outb(j, tmport);
+ outb(0x00, tmport);
}
tmport = wkport + 0x18;
outb(0x08, tmport);
@@ -1224,6 +1281,7 @@
printk(KERN_INFO " ID: %2d %s\n", i, &mbuf[8]);
dev->id[i].devtypeu = mbuf[0];
rmb = mbuf[1];
+ n = mbuf[7];
if (dev->chip_veru != 4) {
goto not_wide;
}
@@ -1234,8 +1292,7 @@
goto not_wide;
}
tmport = wkport + 0x1b;
- j = (inb(tmport) & 0x0e) | 0x01;
- outb(j, tmport);
+ outb(0x01, tmport);
tmport = wkport + 3;
outb(satn[0], tmport++);
outb(satn[1], tmport++);
@@ -1374,13 +1431,15 @@
m = m << i;
dev->wide_idu |= m;
not_wide:
- if ((dev->id[i].devtypeu == 0x00) || (dev->id[i].devtypeu == 0x07)) {
+ if ((dev->id[i].devtypeu == 0x00) || (dev->id[i].devtypeu == 0x07) ||
+ ((dev->id[i].devtypeu == 0x05) && ((n & 0x10) != 0)))
+ {
goto set_sync;
}
continue;
set_sync:
tmport = wkport + 0x1b;
- j = inb(tmport) & 0x0e;
+ j = 0;
if ((m & dev->wide_idu) != 0) {
j |= 0x01;
}
@@ -1420,17 +1479,13 @@
while ((inb(tmport) & 0x80) == 0) {
if ((inb(tmport) & 0x01) != 0) {
tmport -= 0x06;
- if (rmb != 0) {
- outb(synn[j++], tmport);
+ if ((m & dev->wide_idu) != 0) {
+ outb(synw[j++], tmport);
} else {
- if ((m & dev->wide_idu) != 0) {
- outb(synw[j++], tmport);
+ if ((m & dev->ultra_map) != 0) {
+ outb(synu[j++], tmport);
} else {
- if ((m & dev->ultra_map) != 0) {
- outb(synu[j++], tmport);
- } else {
- outb(synn[j++], tmport);
- }
+ outb(synn[j++], tmport);
}
}
tmport += 0x06;
@@ -1579,9 +1634,9 @@
int tmpcnt = 0;
int count = 0;
int result;
-
- static unsigned short devid[7] = {
- 0x8002, 0x8010, 0x8020, 0x8030, 0x8040, 0x8050, 0
+
+ static unsigned short devid[8] = {
+ 0x8002, 0x8010, 0x8020, 0x8030, 0x8040, 0x8050, 0x8060, 0
};
printk(KERN_INFO "aec671x_detect: \n");
@@ -1662,7 +1717,7 @@
base_io &= 0xfffffff8;
if (check_region(base_io,0x40) != 0)
- {
+ {
return 0;
}
printk(KERN_INFO " ACARD AEC-671X PCI Ultra/W SCSI-3 Host Adapter: %d IO:%x, IRQ:%d.\n"
@@ -1692,6 +1747,13 @@
printk(KERN_ERR "Unable to allocate IRQ for Acard controller.\n");
goto unregister;
}
+
+ if (chip_ver[h] > 0x07) /* check if atp876 chip */
+ { /* then enable terminator */
+ tmport = base_io + 0x3e;
+ outb(0x30, tmport);
+ }
+
tmport = base_io + 0x3a;
k = (inb(tmport) & 0xf3) | 0x10;
outb(k, tmport);
@@ -1730,7 +1792,7 @@
shpnt->n_io_port = 0x40; /* Number of bytes of I/O space used */
shpnt->irq = irq;
restore_flags(flags);
- request_region(base_io, 0x40, "atp870u"); /* Register the IO ports that we use */
+ request_region(base_io, 0x40, "atp870u"); /* Register the IO ports that we use */
count++;
index++;
continue;
@@ -1793,7 +1855,7 @@
}
panic("Reset bus host not found !");
find_host:
-/* SCpnt->result = 0x00080000;
+/* SCpnt->result = 0x00080000;
SCpnt->scsi_done(SCpnt);
dev->working=0;
dev->quhdu=0;
@@ -1806,14 +1868,14 @@
{
static char buffer[128];
- strcpy(buffer, "ACARD AEC-6710/6712 PCI Ultra/W SCSI-3 Adapter Driver V2.0+ac ");
+ strcpy(buffer, "ACARD AEC-6710/6712 PCI Ultra/W SCSI-3 Adapter Driver V2.1+ac ");
return buffer;
}
int atp870u_set_info(char *buffer, int length, struct Scsi_Host *HBAptr)
{
- return -ENOSYS; /* Currently this is a no-op */
+ return -ENOSYS; /* Currently this is a no-op */
}
#define BLS buffer + len + size
@@ -1851,7 +1913,7 @@
if (offset == 0) {
memset(buff, 0, sizeof(buff));
}
- size += sprintf(BLS, "ACARD AEC-671X Driver Version: 2.0+ac\n");
+ size += sprintf(BLS, "ACARD AEC-671X Driver Version: 2.1+ac\n");
len += size;
pos = begin + len;
size = 0;
@@ -1899,7 +1961,7 @@
int atp870u_release (struct Scsi_Host *pshost)
{
int h;
- for (h = 0; h <= admaxu; h++)
+ for (h = 0; h <= admaxu; h++)
{
if (pshost == atp_host[h]) {
int k;
@@ -1912,7 +1974,7 @@
}
}
panic("atp870u: bad scsi host passed.\n");
-
+
}
#ifdef MODULE
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)