Commit 2d978494 authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

[PATCH] Add ATP88x support to the ATP870U driver (Vendor patch)

Patch-by: ARTOP Corp.

Basically this adds the small bits for the new card and makes one set of items
an array because the new card is multi-channel.
Signed-off-by: default avatarAlan Cox <alan@redhat.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent f2f33312
...@@ -273,8 +273,8 @@ config SCSI_ACARD ...@@ -273,8 +273,8 @@ config SCSI_ACARD
tristate "ACARD SCSI support" tristate "ACARD SCSI support"
depends on PCI && SCSI depends on PCI && SCSI
help help
This driver supports the ACARD 870U/W SCSI host adapter. This driver supports the ACARD SCSI host adapter.
Support Chip <ATP870 ATP876 ATP880 ATP885>
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called atp870u. module will be called atp870u.
......
/* /*
* Copyright (C) 1997 Wu Ching Chen * Copyright (C) 1997 Wu Ching Chen
* 2.1.x update (C) 1998 Krzysztof G. Baranowski * 2.1.x update (C) 1998 Krzysztof G. Baranowski
* 2.5.x update (C) 2002 Red Hat <alan@redhat.com> * 2.5.x update (C) 2002 Red Hat <alan@redhat.com>
...@@ -13,8 +13,9 @@ ...@@ -13,8 +13,9 @@
* fix disconnect bug 2000/12/21 * fix disconnect bug 2000/12/21
* support atp880 chip lvd u160 2001/05/15 * support atp880 chip lvd u160 2001/05/15
* fix prd table bug 2001/09/12 (7.1) * fix prd table bug 2001/09/12 (7.1)
*
* atp885 support add by ACARD Hao Ping Lian 2005/01/05
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
...@@ -38,39 +39,54 @@ ...@@ -38,39 +39,54 @@
#include "atp870u.h" #include "atp870u.h"
static struct scsi_host_template atp870u_template; static struct scsi_host_template atp870u_template;
static void send_s870(struct Scsi_Host *host); void send_s870(struct atp_unit *dev,unsigned char c);
void is885(struct atp_unit *dev, unsigned int wkport,unsigned char c);
void tscam_885(void);
static irqreturn_t atp870u_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
static irqreturn_t atp870u_intr_handle(int irq, void *dev_id,
struct pt_regs *regs)
{ {
unsigned long flags; unsigned long flags;
unsigned short int tmpcip, id; unsigned short int tmpcip, id;
unsigned char i, j, target_id, lun; unsigned char i, j, c, target_id, lun,cmdp;
unsigned char *prd; unsigned char *prd;
struct scsi_cmnd *workrequ; struct scsi_cmnd *workreq;
unsigned int workportu, tmport; unsigned int workport, tmport, tmport1;
unsigned long adrcntu, k; unsigned long adrcnt, k;
#ifdef ED_DBGP
unsigned long l;
#endif
int errstus; int errstus;
struct Scsi_Host *host = dev_id; struct Scsi_Host *host = dev_id;
struct atp_unit *dev = (struct atp_unit *)&host->hostdata; struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
dev->in_int = 1; for (c = 0; c < 2; c++) {
workportu = dev->ioport; tmport = dev->ioport[c] + 0x1f;
tmport = workportu;
if (dev->working != 0) {
tmport += 0x1f;
j = inb(tmport); j = inb(tmport);
if ((j & 0x80) == 0) { if ((j & 0x80) != 0)
dev->in_int = 0; {
return IRQ_NONE; goto ch_sel;
} }
dev->in_int[c] = 0;
tmpcip = dev->pciport; }
if ((inb(tmpcip) & 0x08) != 0) { return IRQ_NONE;
ch_sel:
#ifdef ED_DBGP
printk("atp870u_intr_handle enter\n");
#endif
dev->in_int[c] = 1;
cmdp = inb(dev->ioport[c] + 0x10);
workport = dev->ioport[c];
if (dev->working[c] != 0) {
if (dev->dev_id == ATP885_DEVID) {
tmport1 = workport + 0x16;
if ((inb(tmport1) & 0x80) == 0)
outb((inb(tmport1) | 0x80), tmport1);
}
tmpcip = dev->pciport[c];
if ((inb(tmpcip) & 0x08) != 0)
{
tmpcip += 0x2; tmpcip += 0x2;
for (k = 0; k < 1000; k++) { for (k=0; k < 1000; k++) {
if ((inb(tmpcip) & 0x08) == 0) { if ((inb(tmpcip) & 0x08) == 0) {
goto stop_dma; goto stop_dma;
} }
...@@ -80,18 +96,24 @@ static irqreturn_t atp870u_intr_handle(int irq, void *dev_id, ...@@ -80,18 +96,24 @@ static irqreturn_t atp870u_intr_handle(int irq, void *dev_id,
} }
} }
stop_dma: stop_dma:
tmpcip = dev->pciport; tmpcip = dev->pciport[c];
outb(0x00, tmpcip); outb(0x00, tmpcip);
tmport -= 0x08; tmport -= 0x08;
i = inb(tmport); i = inb(tmport);
if (dev->dev_id == ATP885_DEVID) {
tmpcip += 2;
outb(0x06, tmpcip);
tmpcip -= 2;
}
tmport -= 0x02; tmport -= 0x02;
target_id = inb(tmport); target_id = inb(tmport);
tmport += 0x02; tmport += 0x02;
/* /*
* Remap wide devices onto id numbers * Remap wide devices onto id numbers
*/ */
if ((target_id & 0x40) != 0) { if ((target_id & 0x40) != 0) {
...@@ -101,332 +123,460 @@ static irqreturn_t atp870u_intr_handle(int irq, void *dev_id, ...@@ -101,332 +123,460 @@ static irqreturn_t atp870u_intr_handle(int irq, void *dev_id,
} }
if ((j & 0x40) != 0) { if ((j & 0x40) != 0) {
if (dev->last_cmd == 0xff) { if (dev->last_cmd[c] == 0xff) {
dev->last_cmd = target_id; dev->last_cmd[c] = target_id;
} }
dev->last_cmd |= 0x40; dev->last_cmd[c] |= 0x40;
} }
if (dev->dev_id == ATP885_DEVID)
dev->r1f[c][target_id] |= j;
#ifdef ED_DBGP
printk("atp870u_intr_handle status = %x\n",i);
#endif
if (i == 0x85) { if (i == 0x85) {
if ((dev->last_cmd & 0xf0) != 0x40) { if ((dev->last_cmd[c] & 0xf0) != 0x40) {
dev->last_cmd = 0xff; dev->last_cmd[c] = 0xff;
}
if (dev->dev_id == ATP885_DEVID) {
tmport -= 0x05;
adrcnt = 0;
((unsigned char *) &adrcnt)[2] = inb(tmport++);
((unsigned char *) &adrcnt)[1] = inb(tmport++);
((unsigned char *) &adrcnt)[0] = inb(tmport);
if (dev->id[c][target_id].last_len != adrcnt)
{
k = dev->id[c][target_id].last_len;
k -= adrcnt;
dev->id[c][target_id].tran_len = k;
dev->id[c][target_id].last_len = adrcnt;
}
#ifdef ED_DBGP
printk("tmport = %x dev->id[c][target_id].last_len = %d dev->id[c][target_id].tran_len = %d\n",tmport,dev->id[c][target_id].last_len,dev->id[c][target_id].tran_len);
#endif
} }
/* /*
* Flip wide * Flip wide
*/ */
if (dev->wide_idu != 0) { if (dev->wide_id[c] != 0) {
tmport = workportu + 0x1b; tmport = workport + 0x1b;
outb(0x01, tmport); outb(0x01, tmport);
while ((inb(tmport) & 0x01) != 0x01) { while ((inb(tmport) & 0x01) != 0x01) {
outb(0x01, tmport); outb(0x01, tmport);
} }
} }
/* /*
* Issue more commands * Issue more commands
*/ */
spin_lock_irqsave(dev->host->host_lock, flags); spin_lock_irqsave(dev->host->host_lock, flags);
if (((dev->quhdu != dev->quendu) || (dev->last_cmd != 0xff)) && (dev->in_snd == 0)) { if (((dev->quhd[c] != dev->quend[c]) || (dev->last_cmd[c] != 0xff)) &&
send_s870(host); (dev->in_snd[c] == 0)) {
#ifdef ED_DBGP
printk("Call sent_s870\n");
#endif
send_s870(dev,c);
} }
spin_unlock_irqrestore(dev->host->host_lock, flags); spin_unlock_irqrestore(dev->host->host_lock, flags);
/* /*
* Done * Done
*/ */
dev->in_int = 0; dev->in_int[c] = 0;
goto out; #ifdef ED_DBGP
printk("Status 0x85 return\n");
#endif
goto handled;
} }
if (i == 0x40) { if (i == 0x40) {
dev->last_cmd |= 0x40; dev->last_cmd[c] |= 0x40;
dev->in_int = 0; dev->in_int[c] = 0;
goto out; goto handled;
} }
if (i == 0x21) { if (i == 0x21) {
if ((dev->last_cmd & 0xf0) != 0x40) { if ((dev->last_cmd[c] & 0xf0) != 0x40) {
dev->last_cmd = 0xff; dev->last_cmd[c] = 0xff;
} }
tmport -= 0x05; tmport -= 0x05;
adrcntu = 0; adrcnt = 0;
((unsigned char *) &adrcntu)[2] = inb(tmport++); ((unsigned char *) &adrcnt)[2] = inb(tmport++);
((unsigned char *) &adrcntu)[1] = inb(tmport++); ((unsigned char *) &adrcnt)[1] = inb(tmport++);
((unsigned char *) &adrcntu)[0] = inb(tmport); ((unsigned char *) &adrcnt)[0] = inb(tmport);
k = dev->id[target_id].last_lenu; k = dev->id[c][target_id].last_len;
k -= adrcntu; k -= adrcnt;
dev->id[target_id].tran_lenu = k; dev->id[c][target_id].tran_len = k;
dev->id[target_id].last_lenu = adrcntu; dev->id[c][target_id].last_len = adrcnt;
tmport -= 0x04; tmport -= 0x04;
outb(0x41, tmport); outb(0x41, tmport);
tmport += 0x08; tmport += 0x08;
outb(0x08, tmport); outb(0x08, tmport);
dev->in_int = 0; dev->in_int[c] = 0;
goto out; goto handled;
}
if (dev->dev_id == ATP885_DEVID) {
if ((i == 0x4c) || (i == 0x4d) || (i == 0x8c) || (i == 0x8d)) {
if ((i == 0x4c) || (i == 0x8c))
i=0x48;
else
i=0x49;
}
} }
if ((i == 0x80) || (i == 0x8f)) { if ((i == 0x80) || (i == 0x8f)) {
#ifdef ED_DBGP
printk(KERN_DEBUG "Device reselect\n");
#endif
lun = 0; lun = 0;
tmport -= 0x07; tmport -= 0x07;
j = inb(tmport); if (cmdp == 0x44 || i==0x80) {
if (j == 0x44 || i == 0x80) {
tmport += 0x0d; tmport += 0x0d;
lun = inb(tmport) & 0x07; lun = inb(tmport) & 0x07;
} else { } else {
if ((dev->last_cmd & 0xf0) != 0x40) { if ((dev->last_cmd[c] & 0xf0) != 0x40) {
dev->last_cmd = 0xff; dev->last_cmd[c] = 0xff;
} }
if (j == 0x41) { if (cmdp == 0x41) {
#ifdef ED_DBGP
printk("cmdp = 0x41\n");
#endif
tmport += 0x02; tmport += 0x02;
adrcntu = 0; adrcnt = 0;
((unsigned char *) &adrcntu)[2] = inb(tmport++); ((unsigned char *) &adrcnt)[2] = inb(tmport++);
((unsigned char *) &adrcntu)[1] = inb(tmport++); ((unsigned char *) &adrcnt)[1] = inb(tmport++);
((unsigned char *) &adrcntu)[0] = inb(tmport); ((unsigned char *) &adrcnt)[0] = inb(tmport);
k = dev->id[target_id].last_lenu; k = dev->id[c][target_id].last_len;
k -= adrcntu; k -= adrcnt;
dev->id[target_id].tran_lenu = k; dev->id[c][target_id].tran_len = k;
dev->id[target_id].last_lenu = adrcntu; dev->id[c][target_id].last_len = adrcnt;
tmport += 0x04; tmport += 0x04;
outb(0x08, tmport); outb(0x08, tmport);
dev->in_int = 0; dev->in_int[c] = 0;
goto out; goto handled;
} else { } else {
#ifdef ED_DBGP
printk("cmdp != 0x41\n");
#endif
outb(0x46, tmport); outb(0x46, tmport);
dev->id[target_id].dirctu = 0x00; dev->id[c][target_id].dirct = 0x00;
tmport += 0x02; tmport += 0x02;
outb(0x00, tmport++); outb(0x00, tmport++);
outb(0x00, tmport++); outb(0x00, tmport++);
outb(0x00, tmport++); outb(0x00, tmport++);
tmport += 0x03; tmport += 0x03;
outb(0x08, tmport); outb(0x08, tmport);
dev->in_int = 0; dev->in_int[c] = 0;
goto out; goto handled;
} }
} }
if (dev->last_cmd != 0xff) { if (dev->last_cmd[c] != 0xff) {
dev->last_cmd |= 0x40; dev->last_cmd[c] |= 0x40;
} }
tmport = workportu + 0x10; if (dev->dev_id == ATP885_DEVID) {
outb(0x45, tmport); j = inb(dev->baseport + 0x29) & 0xfe;
tmport += 0x06; outb(j, dev->baseport + 0x29);
tmport = workport + 0x16;
} else {
tmport = workport + 0x10;
outb(0x45, tmport);
tmport += 0x06;
}
target_id = inb(tmport); target_id = inb(tmport);
/* /*
* Remap wide identifiers * Remap wide identifiers
*/ */
if ((target_id & 0x10) != 0) { if ((target_id & 0x10) != 0) {
target_id = (target_id & 0x07) | 0x08; target_id = (target_id & 0x07) | 0x08;
} else { } else {
target_id &= 0x07; target_id &= 0x07;
} }
workrequ = dev->id[target_id].curr_req; if (dev->dev_id == ATP885_DEVID) {
tmport = workportu + 0x0f; tmport = workport + 0x10;
outb(0x45, tmport);
}
workreq = dev->id[c][target_id].curr_req;
#ifdef ED_DBGP
printk(KERN_DEBUG "Channel = %d ID = %d LUN = %d CDB",c,workreq->device->id,workreq->device->lun);
for(l=0;l<workreq->cmd_len;l++)
{
printk(KERN_DEBUG " %x",workreq->cmnd[l]);
}
#endif
tmport = workport + 0x0f;
outb(lun, tmport); outb(lun, tmport);
tmport += 0x02; tmport += 0x02;
outb(dev->id[target_id].devspu, tmport++); outb(dev->id[c][target_id].devsp, tmport++);
adrcntu = dev->id[target_id].tran_lenu; adrcnt = dev->id[c][target_id].tran_len;
k = dev->id[target_id].last_lenu; k = dev->id[c][target_id].last_len;
outb(((unsigned char *) &k)[2], tmport++); outb(((unsigned char *) &k)[2], tmport++);
outb(((unsigned char *) &k)[1], tmport++); outb(((unsigned char *) &k)[1], tmport++);
outb(((unsigned char *) &k)[0], tmport++); outb(((unsigned char *) &k)[0], tmport++);
#ifdef ED_DBGP
printk("k %x, k[0] 0x%x k[1] 0x%x k[2] 0x%x\n", k, inb(tmport-1), inb(tmport-2), inb(tmport-3));
#endif
/* Remap wide */ /* Remap wide */
j = target_id; j = target_id;
if (target_id > 7) { if (target_id > 7) {
j = (j & 0x07) | 0x40; j = (j & 0x07) | 0x40;
} }
/* Add direction */ /* Add direction */
j |= dev->id[target_id].dirctu; j |= dev->id[c][target_id].dirct;
outb(j, tmport++); outb(j, tmport++);
outb(0x80, tmport); outb(0x80,tmport);
/* enable 32 bit fifo transfer */ /* enable 32 bit fifo transfer */
if (dev->deviceid != 0x8081) { if (dev->dev_id == ATP885_DEVID) {
tmport = workportu + 0x3a; tmpcip = dev->pciport[c] + 1;
if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) || (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a)) { i=inb(tmpcip) & 0xf3;
outb((unsigned char) ((inb(tmport) & 0xf3) | 0x08), tmport); //j=workreq->cmnd[0];
} else { if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
outb((unsigned char) (inb(tmport) & 0xf3), tmport); i |= 0x0c;
} }
} else { outb(i,tmpcip);
tmport = workportu - 0x05; } else if ((dev->dev_id == ATP880_DEVID1) ||
if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) || (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a)) { (dev->dev_id == ATP880_DEVID2) ) {
tmport = workport - 0x05;
if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
outb((unsigned char) ((inb(tmport) & 0x3f) | 0xc0), tmport); outb((unsigned char) ((inb(tmport) & 0x3f) | 0xc0), tmport);
} else { } else {
outb((unsigned char) (inb(tmport) & 0x3f), tmport); outb((unsigned char) (inb(tmport) & 0x3f), tmport);
} }
} } else {
tmport = workport + 0x3a;
tmport = workportu + 0x1b; if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
outb((unsigned char) ((inb(tmport) & 0xf3) | 0x08), tmport);
} else {
outb((unsigned char) (inb(tmport) & 0xf3), tmport);
}
}
tmport = workport + 0x1b;
j = 0; j = 0;
id = 1; id = 1;
id = id << target_id; id = id << target_id;
/* /*
* Is this a wide device * Is this a wide device
*/ */
if ((id & dev->wide_idu) != 0) { if ((id & dev->wide_id[c]) != 0) {
j |= 0x01; j |= 0x01;
} }
outb(j, tmport); outb(j, tmport);
while ((inb(tmport) & 0x01) != j) { while ((inb(tmport) & 0x01) != j) {
outb(j, tmport); outb(j,tmport);
} }
if (dev->id[c][target_id].last_len == 0) {
if (dev->id[target_id].last_lenu == 0) { tmport = workport + 0x18;
tmport = workportu + 0x18;
outb(0x08, tmport); outb(0x08, tmport);
dev->in_int = 0; dev->in_int[c] = 0;
goto out; #ifdef ED_DBGP
printk("dev->id[c][target_id].last_len = 0\n");
#endif
goto handled;
} }
prd = dev->id[target_id].prd_posu; #ifdef ED_DBGP
while (adrcntu != 0) { printk("target_id = %d adrcnt = %d\n",target_id,adrcnt);
id = ((unsigned short int *) (prd))[2]; #endif
prd = dev->id[c][target_id].prd_pos;
while (adrcnt != 0) {
id = ((unsigned short int *)prd)[2];
if (id == 0) { if (id == 0) {
k = 0x10000; k = 0x10000;
} else { } else {
k = id; k = id;
} }
if (k > adrcntu) { if (k > adrcnt) {
((unsigned short int *) (prd))[2] = (unsigned short int) ((unsigned short int *)prd)[2] = (unsigned short int)
(k - adrcntu); (k - adrcnt);
((unsigned long *) (prd))[0] += adrcntu; ((unsigned long *)prd)[0] += adrcnt;
adrcntu = 0; adrcnt = 0;
dev->id[target_id].prd_posu = prd; dev->id[c][target_id].prd_pos = prd;
} else { } else {
adrcntu -= k; adrcnt -= k;
dev->id[target_id].prdaddru += 0x08; dev->id[c][target_id].prdaddr += 0x08;
prd += 0x08; prd += 0x08;
if (adrcntu == 0) { if (adrcnt == 0) {
dev->id[target_id].prd_posu = prd; dev->id[c][target_id].prd_pos = prd;
} }
} }
} }
tmpcip = dev->pciport + 0x04; tmpcip = dev->pciport[c] + 0x04;
outl(dev->id[target_id].prdaddru, tmpcip); outl(dev->id[c][target_id].prdaddr, tmpcip);
tmpcip -= 0x02; #ifdef ED_DBGP
outb(0x06, tmpcip); printk("dev->id[%d][%d].prdaddr 0x%8x\n", c, target_id, dev->id[c][target_id].prdaddr);
outb(0x00, tmpcip); #endif
tmpcip -= 0x02; if (dev->dev_id == ATP885_DEVID) {
tmport = workportu + 0x18; tmpcip -= 0x04;
} else {
tmpcip -= 0x02;
outb(0x06, tmpcip);
outb(0x00, tmpcip);
tmpcip -= 0x02;
}
tmport = workport + 0x18;
/* /*
* Check transfer direction * Check transfer direction
*/ */
if (dev->id[target_id].dirctu != 0) { if (dev->id[c][target_id].dirct != 0) {
outb(0x08, tmport); outb(0x08, tmport);
outb(0x01, tmpcip); outb(0x01, tmpcip);
dev->in_int = 0; dev->in_int[c] = 0;
goto out; #ifdef ED_DBGP
printk("status 0x80 return dirct != 0\n");
#endif
goto handled;
} }
outb(0x08, tmport); outb(0x08, tmport);
outb(0x09, tmpcip); outb(0x09, tmpcip);
dev->in_int = 0; dev->in_int[c] = 0;
goto out; #ifdef ED_DBGP
printk("status 0x80 return dirct = 0\n");
#endif
goto handled;
} }
/* /*
* Current scsi request on this target * Current scsi request on this target
*/ */
workrequ = dev->id[target_id].curr_req; workreq = dev->id[c][target_id].curr_req;
if (i == 0x42) { if (i == 0x42) {
if ((dev->last_cmd & 0xf0) != 0x40) { if ((dev->last_cmd[c] & 0xf0) != 0x40)
dev->last_cmd = 0xff; {
dev->last_cmd[c] = 0xff;
} }
errstus = 0x02; errstus = 0x02;
workrequ->result = errstus; workreq->result = errstus;
goto go_42; goto go_42;
} }
if (i == 0x16) { if (i == 0x16) {
if ((dev->last_cmd & 0xf0) != 0x40) { if ((dev->last_cmd[c] & 0xf0) != 0x40) {
dev->last_cmd = 0xff; dev->last_cmd[c] = 0xff;
} }
errstus = 0; errstus = 0;
tmport -= 0x08; tmport -= 0x08;
errstus = inb(tmport); errstus = inb(tmport);
workrequ->result = errstus; if (((dev->r1f[c][target_id] & 0x10) != 0)&&(dev->dev_id==ATP885_DEVID)) {
printk(KERN_WARNING "AEC67162 CRC ERROR !\n");
errstus = 0x02;
}
workreq->result = errstus;
go_42: go_42:
if (dev->dev_id == ATP885_DEVID) {
j = inb(dev->baseport + 0x29) | 0x01;
outb(j, dev->baseport + 0x29);
}
/* /*
* Complete the command * Complete the command
*/ */
if (workreq->use_sg) {
if (workrequ->use_sg) {
pci_unmap_sg(dev->pdev, pci_unmap_sg(dev->pdev,
(struct scatterlist *)workrequ->buffer, (struct scatterlist *)workreq->buffer,
workrequ->use_sg, workreq->use_sg,
workrequ->sc_data_direction); workreq->sc_data_direction);
} else if (workrequ->request_bufflen && } else if (workreq->request_bufflen &&
workrequ->sc_data_direction != DMA_NONE) { workreq->sc_data_direction != DMA_NONE) {
pci_unmap_single(dev->pdev, pci_unmap_single(dev->pdev,
workrequ->SCp.dma_handle, workreq->SCp.dma_handle,
workrequ->request_bufflen, workreq->request_bufflen,
workrequ->sc_data_direction); workreq->sc_data_direction);
} }
spin_lock_irqsave(dev->host->host_lock, flags); spin_lock_irqsave(dev->host->host_lock, flags);
(*workrequ->scsi_done) (workrequ); (*workreq->scsi_done) (workreq);
#ifdef ED_DBGP
printk("workreq->scsi_done\n");
#endif
/* /*
* Clear it off the queue * Clear it off the queue
*/ */
dev->id[target_id].curr_req = NULL; dev->id[c][target_id].curr_req = 0;
dev->working--; dev->working[c]--;
spin_unlock_irqrestore(dev->host->host_lock, flags); spin_unlock_irqrestore(dev->host->host_lock, flags);
/* /*
* Take it back wide * Take it back wide
*/ */
if (dev->wide_idu != 0) { if (dev->wide_id[c] != 0) {
tmport = workportu + 0x1b; tmport = workport + 0x1b;
outb(0x01, tmport); outb(0x01, tmport);
while ((inb(tmport) & 0x01) != 0x01) { while ((inb(tmport) & 0x01) != 0x01) {
outb(0x01, tmport); outb(0x01, tmport);
} }
} }
/* /*
* If there is stuff to send and nothing going then send it * If there is stuff to send and nothing going then send it
*/ */
spin_lock_irqsave(dev->host->host_lock, flags); spin_lock_irqsave(dev->host->host_lock, flags);
if (((dev->last_cmd != 0xff) || (dev->quhdu != dev->quendu)) && (dev->in_snd == 0)) { if (((dev->last_cmd[c] != 0xff) || (dev->quhd[c] != dev->quend[c])) &&
send_s870(host); (dev->in_snd[c] == 0)) {
#ifdef ED_DBGP
printk("Call sent_s870(scsi_done)\n");
#endif
send_s870(dev,c);
} }
spin_unlock_irqrestore(dev->host->host_lock, flags); spin_unlock_irqrestore(dev->host->host_lock, flags);
dev->in_int = 0; dev->in_int[c] = 0;
goto out; goto handled;
} }
if ((dev->last_cmd & 0xf0) != 0x40) { if ((dev->last_cmd[c] & 0xf0) != 0x40) {
dev->last_cmd = 0xff; dev->last_cmd[c] = 0xff;
} }
if (i == 0x4f) { if (i == 0x4f) {
i = 0x89; i = 0x89;
} }
i &= 0x0f; i &= 0x0f;
if (i == 0x09) { if (i == 0x09) {
tmpcip = tmpcip + 4; tmpcip += 4;
outl(dev->id[target_id].prdaddru, tmpcip); outl(dev->id[c][target_id].prdaddr, tmpcip);
tmpcip = tmpcip - 2; tmpcip = tmpcip - 2;
outb(0x06, tmpcip); outb(0x06, tmpcip);
outb(0x00, tmpcip); outb(0x00, tmpcip);
tmpcip = tmpcip - 2; tmpcip = tmpcip - 2;
tmport = workportu + 0x10; tmport = workport + 0x10;
outb(0x41, tmport); outb(0x41, tmport);
dev->id[target_id].dirctu = 0x00; if (dev->dev_id == ATP885_DEVID) {
tmport += 0x08; tmport += 2;
k = dev->id[c][target_id].last_len;
outb((unsigned char) (((unsigned char *) (&k))[2]), tmport++);
outb((unsigned char) (((unsigned char *) (&k))[1]), tmport++);
outb((unsigned char) (((unsigned char *) (&k))[0]), tmport);
dev->id[c][target_id].dirct = 0x00;
tmport += 0x04;
} else {
dev->id[c][target_id].dirct = 0x00;
tmport += 0x08;
}
outb(0x08, tmport); outb(0x08, tmport);
outb(0x09, tmpcip); outb(0x09, tmpcip);
dev->in_int = 0; dev->in_int[c] = 0;
goto out; goto handled;
} }
if (i == 0x08) { if (i == 0x08) {
tmpcip = tmpcip + 4; tmpcip += 4;
outl(dev->id[target_id].prdaddru, tmpcip); outl(dev->id[c][target_id].prdaddr, tmpcip);
tmpcip = tmpcip - 2; tmpcip = tmpcip - 2;
outb(0x06, tmpcip); outb(0x06, tmpcip);
outb(0x00, tmpcip); outb(0x00, tmpcip);
tmpcip = tmpcip - 2; tmpcip = tmpcip - 2;
tmport = workportu + 0x10; tmport = workport + 0x10;
outb(0x41, tmport); outb(0x41, tmport);
tmport += 0x05; if (dev->dev_id == ATP885_DEVID) {
tmport += 2;
k = dev->id[c][target_id].last_len;
outb((unsigned char) (((unsigned char *) (&k))[2]), tmport++);
outb((unsigned char) (((unsigned char *) (&k))[1]), tmport++);
outb((unsigned char) (((unsigned char *) (&k))[0]), tmport++);
} else {
tmport += 5;
}
outb((unsigned char) (inb(tmport) | 0x20), tmport); outb((unsigned char) (inb(tmport) | 0x20), tmport);
dev->id[target_id].dirctu = 0x20; dev->id[c][target_id].dirct = 0x20;
tmport += 0x03; tmport += 0x03;
outb(0x08, tmport); outb(0x08, tmport);
outb(0x01, tmpcip); outb(0x01, tmpcip);
dev->in_int = 0; dev->in_int[c] = 0;
goto out; goto handled;
} }
tmport -= 0x07; tmport -= 0x07;
if (i == 0x0a) { if (i == 0x0a) {
...@@ -434,25 +584,29 @@ static irqreturn_t atp870u_intr_handle(int irq, void *dev_id, ...@@ -434,25 +584,29 @@ static irqreturn_t atp870u_intr_handle(int irq, void *dev_id,
} else { } else {
outb(0x46, tmport); outb(0x46, tmport);
} }
dev->id[target_id].dirctu = 0x00; dev->id[c][target_id].dirct = 0x00;
tmport += 0x02; tmport += 0x02;
outb(0x00, tmport++); outb(0x00, tmport++);
outb(0x00, tmport++); outb(0x00, tmport++);
outb(0x00, tmport++); outb(0x00, tmport++);
tmport += 0x03; tmport += 0x03;
outb(0x08, tmport); outb(0x08, tmport);
dev->in_int = 0; dev->in_int[c] = 0;
goto out; goto handled;
} else { } else {
// tmport = workportu + 0x17; // tmport = workport + 0x17;
// inb(tmport); // inb(tmport);
// dev->working = 0; // dev->working[c] = 0;
dev->in_int = 0; dev->in_int[c] = 0;
goto handled;
} }
out:
handled:
#ifdef ED_DBGP
printk("atp870u_intr_handle exit\n");
#endif
return IRQ_HANDLED; return IRQ_HANDLED;
} }
/** /**
* atp870u_queuecommand - Queue SCSI command * atp870u_queuecommand - Queue SCSI command
* @req_p: request block * @req_p: request block
...@@ -460,24 +614,30 @@ static irqreturn_t atp870u_intr_handle(int irq, void *dev_id, ...@@ -460,24 +614,30 @@ static irqreturn_t atp870u_intr_handle(int irq, void *dev_id,
* *
* Queue a command to the ATP queue. Called with the host lock held. * Queue a command to the ATP queue. Called with the host lock held.
*/ */
int atp870u_queuecommand(struct scsi_cmnd * req_p, void (*done) (struct scsi_cmnd *))
static int atp870u_queuecommand(struct scsi_cmnd *req_p,
void (*done) (struct scsi_cmnd *))
{ {
unsigned short int m; unsigned char c;
unsigned int tmport; unsigned int tmport,m;
struct Scsi_Host *host;
struct atp_unit *dev; struct atp_unit *dev;
struct Scsi_Host *host;
if (req_p->device->channel != 0) { c = req_p->device->channel;
req_p->sense_buffer[0]=0;
req_p->resid = 0;
if (req_p->device->channel > 1) {
req_p->result = 0x00040000; req_p->result = 0x00040000;
done(req_p); done(req_p);
#ifdef ED_DBGP
printk("atp870u_queuecommand : req_p->device->channel > 1\n");
#endif
return 0; return 0;
}; }
host = req_p->device->host; host = req_p->device->host;
dev = (struct atp_unit *)&host->hostdata; dev = (struct atp_unit *)&host->hostdata;
m = 1; m = 1;
m = m << req_p->device->id; m = m << req_p->device->id;
...@@ -485,44 +645,60 @@ static int atp870u_queuecommand(struct scsi_cmnd *req_p, ...@@ -485,44 +645,60 @@ static int atp870u_queuecommand(struct scsi_cmnd *req_p,
* Fake a timeout for missing targets * Fake a timeout for missing targets
*/ */
if ((m & dev->active_idu) == 0) { if ((m & dev->active_id[c]) == 0) {
req_p->result = 0x00040000; req_p->result = 0x00040000;
done(req_p); done(req_p);
return 0; return 0;
} }
if (done) { if (done) {
req_p->scsi_done = done; req_p->scsi_done = done;
} else { } else {
printk(KERN_WARNING "atp870u_queuecommand: done can't be NULL\n"); #ifdef ED_DBGP
printk( "atp870u_queuecommand: done can't be NULL\n");
#endif
req_p->result = 0; req_p->result = 0;
done(req_p); done(req_p);
return 0; return 0;
} }
/* /*
* Count new command * Count new command
*/ */
dev->quend[c]++;
dev->quendu++; if (dev->quend[c] >= qcnt) {
if (dev->quendu >= qcnt) { dev->quend[c] = 0;
dev->quendu = 0;
} }
/* /*
* Check queue state * Check queue state
*/ */
if (dev->quhdu == dev->quendu) { if (dev->quhd[c] == dev->quend[c]) {
if (dev->quendu == 0) { if (dev->quend[c] == 0) {
dev->quendu = qcnt; dev->quend[c] = qcnt;
} }
dev->quendu--; #ifdef ED_DBGP
printk("atp870u_queuecommand : dev->quhd[c] == dev->quend[c]\n");
#endif
dev->quend[c]--;
req_p->result = 0x00020000; req_p->result = 0x00020000;
done(req_p); done(req_p);
return 0; return 0;
} }
dev->querequ[dev->quendu] = req_p; dev->quereq[c][dev->quend[c]] = req_p;
tmport = dev->ioport + 0x1c; tmport = dev->ioport[c] + 0x1c;
if ((inb(tmport) == 0) && (dev->in_int == 0) && (dev->in_snd == 0)) { #ifdef ED_DBGP
send_s870(host); printk("dev->ioport[c] = %x inb(tmport) = %x dev->in_int[%d] = %d dev->in_snd[%d] = %d\n",dev->ioport[c],inb(tmport),c,dev->in_int[c],c,dev->in_snd[c]);
} #endif
if ((inb(tmport) == 0) && (dev->in_int[c] == 0) && (dev->in_snd[c] == 0)) {
#ifdef ED_DBGP
printk("Call sent_s870(atp870u_queuecommand)\n");
#endif
send_s870(dev,c);
}
#ifdef ED_DBGP
printk("atp870u_queuecommand : exit\n");
#endif
return 0; return 0;
} }
...@@ -535,194 +711,270 @@ static int atp870u_queuecommand(struct scsi_cmnd *req_p, ...@@ -535,194 +711,270 @@ static int atp870u_queuecommand(struct scsi_cmnd *req_p,
* *
* Caller holds the host lock. * Caller holds the host lock.
*/ */
void send_s870(struct atp_unit *dev,unsigned char c)
static void send_s870(struct Scsi_Host *host)
{ {
unsigned int tmport; unsigned int tmport;
struct scsi_cmnd *workrequ; struct scsi_cmnd *workreq;
unsigned int i; unsigned int i;//,k;
unsigned char j, target_id; unsigned char j, target_id;
unsigned char *prd; unsigned char *prd;
unsigned short int tmpcip, w; unsigned short int tmpcip, w;
unsigned long l; unsigned long l, bttl = 0;
dma_addr_t bttl; unsigned int workport;
unsigned int workportu;
struct scatterlist *sgpnt; struct scatterlist *sgpnt;
struct atp_unit *dev = (struct atp_unit *)&host->hostdata; unsigned long sg_count;
int sg_count;
if (dev->in_snd != 0) { if (dev->in_snd[c] != 0) {
return; #ifdef ED_DBGP
} printk("cmnd in_snd\n");
dev->in_snd = 1; #endif
if ((dev->last_cmd != 0xff) && ((dev->last_cmd & 0x40) != 0)) {
dev->last_cmd &= 0x0f;
workrequ = dev->id[dev->last_cmd].curr_req;
if (workrequ != NULL) { /* check NULL pointer */
goto cmd_subp;
}
dev->last_cmd = 0xff;
if (dev->quhdu == dev->quendu) {
dev->in_snd = 0;
return;
}
}
if ((dev->last_cmd != 0xff) && (dev->working != 0)) {
dev->in_snd = 0;
return; return;
} }
dev->working++; #ifdef ED_DBGP
j = dev->quhdu; printk("Sent_s870 enter\n");
dev->quhdu++; #endif
if (dev->quhdu >= qcnt) { dev->in_snd[c] = 1;
dev->quhdu = 0; if ((dev->last_cmd[c] != 0xff) && ((dev->last_cmd[c] & 0x40) != 0)) {
} dev->last_cmd[c] &= 0x0f;
workrequ = dev->querequ[dev->quhdu]; workreq = dev->id[c][dev->last_cmd[c]].curr_req;
if (dev->id[workrequ->device->id].curr_req == 0) { if (workreq != NULL) { /* check NULL pointer */
dev->id[workrequ->device->id].curr_req = workrequ; goto cmd_subp;
dev->last_cmd = workrequ->device->id; }
dev->last_cmd[c] = 0xff;
if (dev->quhd[c] == dev->quend[c]) {
dev->in_snd[c] = 0;
return ;
}
}
if ((dev->last_cmd[c] != 0xff) && (dev->working[c] != 0)) {
dev->in_snd[c] = 0;
return ;
}
dev->working[c]++;
j = dev->quhd[c];
dev->quhd[c]++;
if (dev->quhd[c] >= qcnt) {
dev->quhd[c] = 0;
}
workreq = dev->quereq[c][dev->quhd[c]];
if (dev->id[c][workreq->device->id].curr_req == 0) {
dev->id[c][workreq->device->id].curr_req = workreq;
dev->last_cmd[c] = workreq->device->id;
goto cmd_subp; goto cmd_subp;
} }
dev->quhdu = j; dev->quhd[c] = j;
dev->working--; dev->working[c]--;
dev->in_snd = 0; dev->in_snd[c] = 0;
return; return;
cmd_subp: cmd_subp:
workportu = dev->ioport; workport = dev->ioport[c];
tmport = workportu + 0x1f; tmport = workport + 0x1f;
if ((inb(tmport) & 0xb0) != 0) { if ((inb(tmport) & 0xb0) != 0) {
goto abortsnd; goto abortsnd;
} }
tmport = workportu + 0x1c; tmport = workport + 0x1c;
if (inb(tmport) == 0) { if (inb(tmport) == 0) {
goto oktosend; goto oktosend;
} }
abortsnd: abortsnd:
dev->last_cmd |= 0x40; #ifdef ED_DBGP
dev->in_snd = 0; printk("Abort to Send\n");
#endif
dev->last_cmd[c] |= 0x40;
dev->in_snd[c] = 0;
return; return;
oktosend: oktosend:
memcpy(&dev->ata_cdbu[0], &workrequ->cmnd[0], workrequ->cmd_len); #ifdef ED_DBGP
if (dev->ata_cdbu[0] == READ_CAPACITY) { printk("OK to Send\n");
if (workrequ->request_bufflen > 8) { printk("CDB");
workrequ->request_bufflen = 0x08; for(i=0;i<workreq->cmd_len;i++) {
printk(" %x",workreq->cmnd[i]);
}
printk("\nChannel = %d ID = %d LUN = %d\n",c,workreq->device->id,workreq->device->lun);
#endif
if (dev->dev_id == ATP885_DEVID) {
j = inb(dev->baseport + 0x29) & 0xfe;
outb(j, dev->baseport + 0x29);
dev->r1f[c][workreq->device->id] = 0;
}
if (workreq->cmnd[0] == READ_CAPACITY) {
if (workreq->request_bufflen > 8) {
workreq->request_bufflen = 0x08;
} }
} }
if (dev->ata_cdbu[0] == 0x00) { if (workreq->cmnd[0] == 0x00) {
workrequ->request_bufflen = 0; workreq->request_bufflen = 0;
} }
tmport = workportu + 0x1b; tmport = workport + 0x1b;
j = 0; j = 0;
target_id = workrequ->device->id; target_id = workreq->device->id;
/* /*
* Wide ? * Wide ?
*/ */
w = 1; w = 1;
w = w << target_id; w = w << target_id;
if ((w & dev->wide_idu) != 0) { if ((w & dev->wide_id[c]) != 0) {
j |= 0x01; j |= 0x01;
} }
outb(j, tmport); outb(j, tmport);
while ((inb(tmport) & 0x01) != j) { while ((inb(tmport) & 0x01) != j) {
outb(j, tmport); outb(j,tmport);
#ifdef ED_DBGP
printk("send_s870 while loop 1\n");
#endif
} }
/* /*
* Write the command * Write the command
*/ */
tmport = workportu; tmport = workport;
outb(workrequ->cmd_len, tmport++); outb(workreq->cmd_len, tmport++);
outb(0x2c, tmport++); outb(0x2c, tmport++);
outb(0xcf, tmport++); if (dev->dev_id == ATP885_DEVID) {
for (i = 0; i < workrequ->cmd_len; i++) { outb(0x7f, tmport++);
outb(dev->ata_cdbu[i], tmport++); } else {
outb(0xcf, tmport++);
}
for (i = 0; i < workreq->cmd_len; i++) {
outb(workreq->cmnd[i], tmport++);
} }
tmport = workportu + 0x0f; tmport = workport + 0x0f;
outb(workrequ->device->lun, tmport); outb(workreq->device->lun, tmport);
tmport += 0x02; tmport += 0x02;
/* /*
* Write the target * Write the target
*/ */
outb(dev->id[target_id].devspu, tmport++); outb(dev->id[c][target_id].devsp, tmport++);
#ifdef ED_DBGP
printk("dev->id[%d][%d].devsp = %2x\n",c,target_id,dev->id[c][target_id].devsp);
#endif
/* /*
* Figure out the transfer size * Figure out the transfer size
*/ */
if (workrequ->use_sg) { if (workreq->use_sg) {
#ifdef ED_DBGP
printk("Using SGL\n");
#endif
l = 0; l = 0;
sgpnt = (struct scatterlist *) workrequ->request_buffer;
sg_count = pci_map_sg(dev->pdev, sgpnt, workrequ->use_sg, sgpnt = (struct scatterlist *) workreq->request_buffer;
workrequ->sc_data_direction); sg_count = pci_map_sg(dev->pdev, sgpnt, workreq->use_sg,
for (i = 0; i < workrequ->use_sg; i++) { workreq->sc_data_direction);
if (sgpnt[i].length == 0 || workrequ->use_sg > ATP870U_SCATTER) {
for (i = 0; i < workreq->use_sg; i++) {
if (sgpnt[i].length == 0 || workreq->use_sg > ATP870U_SCATTER) {
panic("Foooooooood fight!"); panic("Foooooooood fight!");
} }
l += sgpnt[i].length; l += sgpnt[i].length;
} }
} else if(workrequ->request_bufflen && workrequ->sc_data_direction != PCI_DMA_NONE) { #ifdef ED_DBGP
workrequ->SCp.dma_handle = pci_map_single(dev->pdev, printk( "send_s870: workreq->use_sg %d, sg_count %d l %8ld\n", workreq->use_sg, sg_count, l);
workrequ->request_buffer, #endif
workrequ->request_bufflen, } else if(workreq->request_bufflen && workreq->sc_data_direction != PCI_DMA_NONE) {
workrequ->sc_data_direction); #ifdef ED_DBGP
l = workrequ->request_bufflen; printk("Not using SGL\n");
} #endif
else l = 0; workreq->SCp.dma_handle = pci_map_single(dev->pdev, workreq->request_buffer,
workreq->request_bufflen,
workreq->sc_data_direction);
l = workreq->request_bufflen;
#ifdef ED_DBGP
printk( "send_s870: workreq->use_sg %d, l %8ld\n", workreq->use_sg, l);
#endif
} else l = 0;
/* /*
* Write transfer size * Write transfer size
*/ */
outb((unsigned char) (((unsigned char *) (&l))[2]), tmport++); outb((unsigned char) (((unsigned char *) (&l))[2]), tmport++);
outb((unsigned char) (((unsigned char *) (&l))[1]), tmport++); outb((unsigned char) (((unsigned char *) (&l))[1]), tmport++);
outb((unsigned char) (((unsigned char *) (&l))[0]), tmport++); outb((unsigned char) (((unsigned char *) (&l))[0]), tmport++);
j = target_id; j = target_id;
dev->id[j].last_lenu = l; dev->id[c][j].last_len = l;
dev->id[j].tran_lenu = 0; dev->id[c][j].tran_len = 0;
#ifdef ED_DBGP
printk("dev->id[%2d][%2d].last_len = %d\n",c,j,dev->id[c][j].last_len);
#endif
/* /*
* Flip the wide bits * Flip the wide bits
*/ */
if ((j & 0x08) != 0) { if ((j & 0x08) != 0) {
j = (j & 0x07) | 0x40; j = (j & 0x07) | 0x40;
} }
/* /*
* Check transfer direction * Check transfer direction
*/ */
if (workrequ->sc_data_direction == DMA_TO_DEVICE) { if (workreq->sc_data_direction == DMA_TO_DEVICE) {
outb((unsigned char) (j | 0x20), tmport++); outb((unsigned char) (j | 0x20), tmport++);
} else { } else {
outb(j, tmport++); outb(j, tmport++);
} }
outb((unsigned char) (inb(tmport) | 0x80), tmport); outb((unsigned char) (inb(tmport) | 0x80), tmport);
outb(0x80, tmport); outb(0x80, tmport);
tmport = workportu + 0x1c; tmport = workport + 0x1c;
dev->id[target_id].dirctu = 0; dev->id[c][target_id].dirct = 0;
if (l == 0) { if (l == 0) {
if (inb(tmport) == 0) { if (inb(tmport) == 0) {
tmport = workportu + 0x18; tmport = workport + 0x18;
#ifdef ED_DBGP
printk("change SCSI_CMD_REG 0x08\n");
#endif
outb(0x08, tmport); outb(0x08, tmport);
} else { } else {
dev->last_cmd |= 0x40; dev->last_cmd[c] |= 0x40;
} }
dev->in_snd = 0; dev->in_snd[c] = 0;
return; return;
} }
tmpcip = dev->pciport; tmpcip = dev->pciport[c];
prd = dev->id[target_id].prd_tableu; prd = dev->id[c][target_id].prd_table;
dev->id[target_id].prd_posu = prd; dev->id[c][target_id].prd_pos = prd;
/* /*
* Now write the request list. Either as scatter/gather or as * Now write the request list. Either as scatter/gather or as
* a linear chain. * a linear chain.
*/ */
if (workrequ->use_sg) { if (workreq->use_sg) {
sgpnt = (struct scatterlist *) workrequ->request_buffer; sgpnt = (struct scatterlist *) workreq->request_buffer;
i = 0; i = 0;
for (j = 0; j < workrequ->use_sg; j++) { for (j = 0; j < workreq->use_sg; j++) {
bttl = sg_dma_address(&sgpnt[j]); bttl = sg_dma_address(&sgpnt[j]);
l = sg_dma_len(&sgpnt[j]); l=sg_dma_len(&sgpnt[j]);
#ifdef ED_DBGP
printk("1. bttl %x, l %x\n",bttl, l);
#endif
while (l > 0x10000) { while (l > 0x10000) {
(((u16 *) (prd))[i + 3]) = 0x0000;
(((u16 *) (prd))[i + 2]) = 0x0000;
(((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
l -= 0x10000;
bttl += 0x10000;
i += 0x04;
}
(((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
(((u16 *) (prd))[i + 2]) = cpu_to_le16(l);
(((u16 *) (prd))[i + 3]) = 0;
i += 0x04;
}
(((u16 *) (prd))[i - 1]) = cpu_to_le16(0x8000);
#ifdef ED_DBGP
printk("prd %4x %4x %4x %4x\n",(((unsigned short int *)prd)[0]),(((unsigned short int *)prd)[1]),(((unsigned short int *)prd)[2]),(((unsigned short int *)prd)[3]));
printk("2. bttl %x, l %x\n",bttl, l);
#endif
} else {
/*
* For a linear request write a chain of blocks
*/
bttl = workreq->SCp.dma_handle;
l = workreq->request_bufflen;
i = 0;
#ifdef ED_DBGP
printk("3. bttl %x, l %x\n",bttl, l);
#endif
while (l > 0x10000) {
(((u16 *) (prd))[i + 3]) = 0x0000; (((u16 *) (prd))[i + 3]) = 0x0000;
(((u16 *) (prd))[i + 2]) = 0x0000; (((u16 *) (prd))[i + 2]) = 0x0000;
(((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl); (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
...@@ -730,76 +982,84 @@ static void send_s870(struct Scsi_Host *host) ...@@ -730,76 +982,84 @@ static void send_s870(struct Scsi_Host *host)
bttl += 0x10000; bttl += 0x10000;
i += 0x04; i += 0x04;
} }
(((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl); (((u16 *) (prd))[i + 3]) = cpu_to_le16(0x8000);
(((u16 *) (prd))[i + 2]) = cpu_to_le16(l); (((u16 *) (prd))[i + 2]) = cpu_to_le16(l);
(((u16 *) (prd))[i + 3]) = 0; (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
i += 0x04; #ifdef ED_DBGP
} printk("prd %4x %4x %4x %4x\n",(((unsigned short int *)prd)[0]),(((unsigned short int *)prd)[1]),(((unsigned short int *)prd)[2]),(((unsigned short int *)prd)[3]));
(((u16 *) (prd))[i - 1]) = cpu_to_le16(0x8000); printk("4. bttl %x, l %x\n",bttl, l);
} else { #endif
/*
* For a linear request write a chain of blocks
*/
bttl = workrequ->SCp.dma_handle;
l = workrequ->request_bufflen;
i = 0;
while (l > 0x10000) {
(((u16 *) (prd))[i + 3]) = 0x0000;
(((u16 *) (prd))[i + 2]) = 0x0000;
(((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
l -= 0x10000;
bttl += 0x10000;
i += 0x04;
}
(((u16 *) (prd))[i + 3]) = cpu_to_le16(0x8000);
(((u16 *) (prd))[i + 2]) = cpu_to_le16(l);
(((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
} }
tmpcip = tmpcip + 4; tmpcip += 4;
dev->id[target_id].prdaddru = dev->id[target_id].prd_phys; #ifdef ED_DBGP
outl(dev->id[target_id].prd_phys, tmpcip); printk("send_s870: prdaddr_1 0x%8x\n", dev->id[c][target_id].prdaddr);
#endif
dev->id[c][target_id].prdaddr = virt_to_bus(dev->id[c][target_id].prd_table);
#ifdef ED_DBGP
printk("send_s870: prdaddr_2 0x%8x tmpcip %x target_id %d\n", dev->id[c][target_id].prdaddr,tmpcip,target_id);
#endif
outl(dev->id[c][target_id].prdaddr, tmpcip);
tmpcip = tmpcip - 2; tmpcip = tmpcip - 2;
outb(0x06, tmpcip); outb(0x06, tmpcip);
outb(0x00, tmpcip); outb(0x00, tmpcip);
tmpcip = tmpcip - 2; if (dev->dev_id == ATP885_DEVID) {
tmpcip--;
if (dev->deviceid != 0x8081) { j=inb(tmpcip) & 0xf3;
tmport = workportu + 0x3a; if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) ||
if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) || (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a)) { (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
outb((inb(tmport) & 0xf3) | 0x08, tmport); j |= 0x0c;
} else { }
outb(inb(tmport) & 0xf3, tmport); outb(j,tmpcip);
} tmpcip--;
} else { } else if ((dev->dev_id == ATP880_DEVID1) ||
tmport = workportu - 0x05; (dev->dev_id == ATP880_DEVID2)) {
if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) || (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a)) { tmpcip =tmpcip -2;
tmport = workport - 0x05;
if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
outb((unsigned char) ((inb(tmport) & 0x3f) | 0xc0), tmport); outb((unsigned char) ((inb(tmport) & 0x3f) | 0xc0), tmport);
} else { } else {
outb((unsigned char) (inb(tmport) & 0x3f), tmport); outb((unsigned char) (inb(tmport) & 0x3f), tmport);
} }
} } else {
tmport = workportu + 0x1c; tmpcip =tmpcip -2;
tmport = workport + 0x3a;
if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
outb((inb(tmport) & 0xf3) | 0x08, tmport);
} else {
outb(inb(tmport) & 0xf3, tmport);
}
}
tmport = workport + 0x1c;
if (workrequ->sc_data_direction == DMA_TO_DEVICE) { if(workreq->sc_data_direction == DMA_TO_DEVICE) {
dev->id[target_id].dirctu = 0x20; dev->id[c][target_id].dirct = 0x20;
if (inb(tmport) == 0) { if (inb(tmport) == 0) {
tmport = workportu + 0x18; tmport = workport + 0x18;
outb(0x08, tmport); outb(0x08, tmport);
outb(0x01, tmpcip); outb(0x01, tmpcip);
#ifdef ED_DBGP
printk( "start DMA(to target)\n");
#endif
} else { } else {
dev->last_cmd |= 0x40; dev->last_cmd[c] |= 0x40;
} }
dev->in_snd = 0; dev->in_snd[c] = 0;
return; return;
} }
if (inb(tmport) == 0) { if (inb(tmport) == 0) {
tmport = workportu + 0x18; tmport = workport + 0x18;
outb(0x08, tmport); outb(0x08, tmport);
outb(0x09, tmpcip); outb(0x09, tmpcip);
#ifdef ED_DBGP
printk( "start DMA(to host)\n");
#endif
} else { } else {
dev->last_cmd |= 0x40; dev->last_cmd[c] |= 0x40;
} }
dev->in_snd = 0; dev->in_snd[c] = 0;
return;
} }
static unsigned char fun_scam(struct atp_unit *dev, unsigned short int *val) static unsigned char fun_scam(struct atp_unit *dev, unsigned short int *val)
...@@ -808,7 +1068,7 @@ static unsigned char fun_scam(struct atp_unit *dev, unsigned short int *val) ...@@ -808,7 +1068,7 @@ static unsigned char fun_scam(struct atp_unit *dev, unsigned short int *val)
unsigned short int i, k; unsigned short int i, k;
unsigned char j; unsigned char j;
tmport = dev->ioport + 0x1c; tmport = dev->ioport[0] + 0x1c;
outw(*val, tmport); outw(*val, tmport);
FUN_D7: FUN_D7:
for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */ for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */
...@@ -863,24 +1123,24 @@ static void tscam(struct Scsi_Host *host) ...@@ -863,24 +1123,24 @@ static void tscam(struct Scsi_Host *host)
} }
*/ */
tmport = dev->ioport + 1; tmport = dev->ioport[0] + 1;
outb(0x08, tmport++); outb(0x08, tmport++);
outb(0x7f, tmport); outb(0x7f, tmport);
tmport = dev->ioport + 0x11; tmport = dev->ioport[0] + 0x11;
outb(0x20, tmport); outb(0x20, tmport);
if ((dev->scam_on & 0x40) == 0) { if ((dev->scam_on & 0x40) == 0) {
return; return;
} }
m = 1; m = 1;
m <<= dev->host_idu; m <<= dev->host_id[0];
j = 16; j = 16;
if (dev->chip_veru < 4) { if (dev->chip_ver < 4) {
m |= 0xff00; m |= 0xff00;
j = 8; j = 8;
} }
assignid_map = m; assignid_map = m;
tmport = dev->ioport + 0x02; tmport = dev->ioport[0] + 0x02;
outb(0x02, tmport++); /* 2*2=4ms,3EH 2/32*3E=3.9ms */ outb(0x02, tmport++); /* 2*2=4ms,3EH 2/32*3E=3.9ms */
outb(0, tmport++); outb(0, tmport++);
outb(0, tmport++); outb(0, tmport++);
...@@ -895,7 +1155,7 @@ static void tscam(struct Scsi_Host *host) ...@@ -895,7 +1155,7 @@ static void tscam(struct Scsi_Host *host)
if ((m & assignid_map) != 0) { if ((m & assignid_map) != 0) {
continue; continue;
} }
tmport = dev->ioport + 0x0f; tmport = dev->ioport[0] + 0x0f;
outb(0, tmport++); outb(0, tmport++);
tmport += 0x02; tmport += 0x02;
outb(0, tmport++); outb(0, tmport++);
...@@ -907,14 +1167,14 @@ static void tscam(struct Scsi_Host *host) ...@@ -907,14 +1167,14 @@ static void tscam(struct Scsi_Host *host)
k = i; k = i;
} }
outb(k, tmport++); outb(k, tmport++);
tmport = dev->ioport + 0x1b; tmport = dev->ioport[0] + 0x1b;
if (dev->chip_veru == 4) { if (dev->chip_ver == 4) {
outb(0x01, tmport); outb(0x01, tmport);
} else { } else {
outb(0x00, tmport); outb(0x00, tmport);
} }
wait_rdyok: wait_rdyok:
tmport = dev->ioport + 0x18; tmport = dev->ioport[0] + 0x18;
outb(0x09, tmport); outb(0x09, tmport);
tmport += 0x07; tmport += 0x07;
...@@ -925,22 +1185,22 @@ static void tscam(struct Scsi_Host *host) ...@@ -925,22 +1185,22 @@ static void tscam(struct Scsi_Host *host)
if ((k == 0x85) || (k == 0x42)) { if ((k == 0x85) || (k == 0x42)) {
continue; continue;
} }
tmport = dev->ioport + 0x10; tmport = dev->ioport[0] + 0x10;
outb(0x41, tmport); outb(0x41, tmport);
goto wait_rdyok; goto wait_rdyok;
} }
assignid_map |= m; assignid_map |= m;
} }
tmport = dev->ioport + 0x02; tmport = dev->ioport[0] + 0x02;
outb(0x7f, tmport); outb(0x7f, tmport);
tmport = dev->ioport + 0x1b; tmport = dev->ioport[0] + 0x1b;
outb(0x02, tmport); outb(0x02, tmport);
outb(0, 0x80); outb(0, 0x80);
val = 0x0080; /* bsy */ val = 0x0080; /* bsy */
tmport = dev->ioport + 0x1c; tmport = dev->ioport[0] + 0x1c;
outw(val, tmport); outw(val, tmport);
val |= 0x0040; /* sel */ val |= 0x0040; /* sel */
outw(val, tmport); outw(val, tmport);
...@@ -984,7 +1244,7 @@ static void tscam(struct Scsi_Host *host) ...@@ -984,7 +1244,7 @@ static void tscam(struct Scsi_Host *host)
if ((inb(tmport) & 0x80) == 0x00) { /* bsy ? */ if ((inb(tmport) & 0x80) == 0x00) { /* bsy ? */
outw(0, tmport--); outw(0, tmport--);
outb(0, tmport); outb(0, tmport);
tmport = dev->ioport + 0x15; tmport = dev->ioport[0] + 0x15;
outb(0, tmport); outb(0, tmport);
tmport += 0x03; tmport += 0x03;
outb(0x09, tmport); outb(0x09, tmport);
...@@ -1085,7 +1345,7 @@ static void tscam(struct Scsi_Host *host) ...@@ -1085,7 +1345,7 @@ static void tscam(struct Scsi_Host *host)
} }
static void is870(struct Scsi_Host *host, unsigned int wkport) void is870(struct atp_unit *dev, unsigned int wkport)
{ {
unsigned int tmport; unsigned int tmport;
unsigned char i, j, k, rmb, n; unsigned char i, j, k, rmb, n;
...@@ -1097,26 +1357,25 @@ static void is870(struct Scsi_Host *host, unsigned int wkport) ...@@ -1097,26 +1357,25 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
static unsigned char synu[6] = { 0x80, 1, 3, 1, 0x0c, 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 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 = (struct atp_unit *)&host->hostdata;
tmport = wkport + 0x3a; tmport = wkport + 0x3a;
outb((unsigned char) (inb(tmport) | 0x10), tmport); outb((unsigned char) (inb(tmport) | 0x10), tmport);
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
if ((dev->chip_veru != 4) && (i > 7)) { if ((dev->chip_ver != 4) && (i > 7)) {
break; break;
} }
m = 1; m = 1;
m = m << i; m = m << i;
if ((m & dev->active_idu) != 0) { if ((m & dev->active_id[0]) != 0) {
continue; continue;
} }
if (i == dev->host_idu) { if (i == dev->host_id[0]) {
printk(KERN_INFO " ID: %2d Host Adapter\n", dev->host_idu); printk(KERN_INFO " ID: %2d Host Adapter\n", dev->host_id[0]);
continue; continue;
} }
tmport = wkport + 0x1b; tmport = wkport + 0x1b;
if (dev->chip_veru == 4) { if (dev->chip_ver == 4) {
outb(0x01, tmport); outb(0x01, tmport);
} else { } else {
outb(0x00, tmport); outb(0x00, tmport);
...@@ -1133,7 +1392,7 @@ static void is870(struct Scsi_Host *host, unsigned int wkport) ...@@ -1133,7 +1392,7 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
tmport += 0x06; tmport += 0x06;
outb(0, tmport); outb(0, tmport);
tmport += 0x02; tmport += 0x02;
outb(dev->id[i].devspu, tmport++); outb(dev->id[0][i].devsp, tmport++);
outb(0, tmport++); outb(0, tmport++);
outb(satn[6], tmport++); outb(satn[6], tmport++);
outb(satn[7], tmport++); outb(satn[7], tmport++);
...@@ -1152,7 +1411,7 @@ static void is870(struct Scsi_Host *host, unsigned int wkport) ...@@ -1152,7 +1411,7 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
continue; continue;
} }
while (inb(tmport) != 0x8e); while (inb(tmport) != 0x8e);
dev->active_idu |= m; dev->active_id[0] |= m;
tmport = wkport + 0x10; tmport = wkport + 0x10;
outb(0x30, tmport); outb(0x30, tmport);
...@@ -1182,7 +1441,7 @@ static void is870(struct Scsi_Host *host, unsigned int wkport) ...@@ -1182,7 +1441,7 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
tmport += 0x07; tmport += 0x07;
outb(0, tmport); outb(0, tmport);
tmport += 0x02; tmport += 0x02;
outb(dev->id[i].devspu, tmport++); outb(dev->id[0][i].devsp, tmport++);
outb(0, tmport++); outb(0, tmport++);
outb(inqd[6], tmport++); outb(inqd[6], tmport++);
outb(inqd[7], tmport++); outb(inqd[7], tmport++);
...@@ -1196,7 +1455,7 @@ static void is870(struct Scsi_Host *host, unsigned int wkport) ...@@ -1196,7 +1455,7 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
} }
while (inb(tmport) != 0x8e); while (inb(tmport) != 0x8e);
tmport = wkport + 0x1b; tmport = wkport + 0x1b;
if (dev->chip_veru == 4) { if (dev->chip_ver == 4) {
outb(0x00, tmport); outb(0x00, tmport);
} }
tmport = wkport + 0x18; tmport = wkport + 0x18;
...@@ -1236,16 +1495,16 @@ static void is870(struct Scsi_Host *host, unsigned int wkport) ...@@ -1236,16 +1495,16 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
inq_ok: inq_ok:
mbuf[36] = 0; mbuf[36] = 0;
printk(KERN_INFO " ID: %2d %s\n", i, &mbuf[8]); printk(KERN_INFO " ID: %2d %s\n", i, &mbuf[8]);
dev->id[i].devtypeu = mbuf[0]; dev->id[0][i].devtype = mbuf[0];
rmb = mbuf[1]; rmb = mbuf[1];
n = mbuf[7]; n = mbuf[7];
if (dev->chip_veru != 4) { if (dev->chip_ver != 4) {
goto not_wide; goto not_wide;
} }
if ((mbuf[7] & 0x60) == 0) { if ((mbuf[7] & 0x60) == 0) {
goto not_wide; goto not_wide;
} }
if ((dev->global_map & 0x20) == 0) { if ((dev->global_map[0] & 0x20) == 0) {
goto not_wide; goto not_wide;
} }
tmport = wkport + 0x1b; tmport = wkport + 0x1b;
...@@ -1260,7 +1519,7 @@ static void is870(struct Scsi_Host *host, unsigned int wkport) ...@@ -1260,7 +1519,7 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
tmport += 0x06; tmport += 0x06;
outb(0, tmport); outb(0, tmport);
tmport += 0x02; tmport += 0x02;
outb(dev->id[i].devspu, tmport++); outb(dev->id[0][i].devsp, tmport++);
outb(0, tmport++); outb(0, tmport++);
outb(satn[6], tmport++); outb(satn[6], tmport++);
outb(satn[7], tmport++); outb(satn[7], tmport++);
...@@ -1386,16 +1645,16 @@ static void is870(struct Scsi_Host *host, unsigned int wkport) ...@@ -1386,16 +1645,16 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
} }
m = 1; m = 1;
m = m << i; m = m << i;
dev->wide_idu |= m; dev->wide_id[0] |= m;
not_wide: not_wide:
if ((dev->id[i].devtypeu == 0x00) || (dev->id[i].devtypeu == 0x07) || ((dev->id[i].devtypeu == 0x05) && ((n & 0x10) != 0))) { if ((dev->id[0][i].devtype == 0x00) || (dev->id[0][i].devtype == 0x07) || ((dev->id[0][i].devtype == 0x05) && ((n & 0x10) != 0))) {
goto set_sync; goto set_sync;
} }
continue; continue;
set_sync: set_sync:
tmport = wkport + 0x1b; tmport = wkport + 0x1b;
j = 0; j = 0;
if ((m & dev->wide_idu) != 0) { if ((m & dev->wide_id[0]) != 0) {
j |= 0x01; j |= 0x01;
} }
outb(j, tmport); outb(j, tmport);
...@@ -1409,7 +1668,7 @@ static void is870(struct Scsi_Host *host, unsigned int wkport) ...@@ -1409,7 +1668,7 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
tmport += 0x06; tmport += 0x06;
outb(0, tmport); outb(0, tmport);
tmport += 0x02; tmport += 0x02;
outb(dev->id[i].devspu, tmport++); outb(dev->id[0][i].devsp, tmport++);
outb(0, tmport++); outb(0, tmport++);
outb(satn[6], tmport++); outb(satn[6], tmport++);
outb(satn[7], tmport++); outb(satn[7], tmport++);
...@@ -1434,10 +1693,10 @@ static void is870(struct Scsi_Host *host, unsigned int wkport) ...@@ -1434,10 +1693,10 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
while ((inb(tmport) & 0x80) == 0) { while ((inb(tmport) & 0x80) == 0) {
if ((inb(tmport) & 0x01) != 0) { if ((inb(tmport) & 0x01) != 0) {
tmport -= 0x06; tmport -= 0x06;
if ((m & dev->wide_idu) != 0) { if ((m & dev->wide_id[0]) != 0) {
outb(synw[j++], tmport); outb(synw[j++], tmport);
} else { } else {
if ((m & dev->ultra_map) != 0) { if ((m & dev->ultra_map[0]) != 0) {
outb(synu[j++], tmport); outb(synu[j++], tmport);
} else { } else {
outb(synn[j++], tmport); outb(synn[j++], tmport);
...@@ -1551,7 +1810,7 @@ static void is870(struct Scsi_Host *host, unsigned int wkport) ...@@ -1551,7 +1810,7 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
if (mbuf[4] > 0x0c) { if (mbuf[4] > 0x0c) {
mbuf[4] = 0x0c; mbuf[4] = 0x0c;
} }
dev->id[i].devspu = mbuf[4]; dev->id[0][i].devsp = mbuf[4];
if ((mbuf[3] < 0x0d) && (rmb == 0)) { if ((mbuf[3] < 0x0d) && (rmb == 0)) {
j = 0xa0; j = 0xa0;
goto set_syn_ok; goto set_syn_ok;
...@@ -1570,13 +1829,13 @@ static void is870(struct Scsi_Host *host, unsigned int wkport) ...@@ -1570,13 +1829,13 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
} }
j = 0x60; j = 0x60;
set_syn_ok: set_syn_ok:
dev->id[i].devspu = (dev->id[i].devspu & 0x0f) | j; dev->id[0][i].devsp = (dev->id[0][i].devsp & 0x0f) | j;
} }
tmport = wkport + 0x3a; tmport = wkport + 0x3a;
outb((unsigned char) (inb(tmport) & 0xef), tmport); outb((unsigned char) (inb(tmport) & 0xef), tmport);
} }
static void is880(struct Scsi_Host *host, unsigned int wkport) static void is880(struct atp_unit *dev, unsigned int wkport)
{ {
unsigned int tmport; unsigned int tmport;
unsigned char i, j, k, rmb, n, lvdmode; unsigned char i, j, k, rmb, n, lvdmode;
...@@ -1590,18 +1849,17 @@ static void is880(struct Scsi_Host *host, unsigned int wkport) ...@@ -1590,18 +1849,17 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
unsigned char synuw[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e }; unsigned char synuw[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e };
static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 }; static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };
static unsigned char u3[9] = { 0x80, 1, 6, 4, 0x09, 00, 0x0e, 0x01, 0x02 }; static unsigned char u3[9] = { 0x80, 1, 6, 4, 0x09, 00, 0x0e, 0x01, 0x02 };
struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
lvdmode = inb(wkport + 0x3f) & 0x40; lvdmode = inb(wkport + 0x3f) & 0x40;
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
m = 1; m = 1;
m = m << i; m = m << i;
if ((m & dev->active_idu) != 0) { if ((m & dev->active_id[0]) != 0) {
continue; continue;
} }
if (i == dev->host_idu) { if (i == dev->host_id[0]) {
printk(KERN_INFO " ID: %2d Host Adapter\n", dev->host_idu); printk(KERN_INFO " ID: %2d Host Adapter\n", dev->host_id[0]);
continue; continue;
} }
tmport = wkport + 0x5b; tmport = wkport + 0x5b;
...@@ -1618,7 +1876,7 @@ static void is880(struct Scsi_Host *host, unsigned int wkport) ...@@ -1618,7 +1876,7 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
tmport += 0x06; tmport += 0x06;
outb(0, tmport); outb(0, tmport);
tmport += 0x02; tmport += 0x02;
outb(dev->id[i].devspu, tmport++); outb(dev->id[0][i].devsp, tmport++);
outb(0, tmport++); outb(0, tmport++);
outb(satn[6], tmport++); outb(satn[6], tmport++);
outb(satn[7], tmport++); outb(satn[7], tmport++);
...@@ -1637,7 +1895,7 @@ static void is880(struct Scsi_Host *host, unsigned int wkport) ...@@ -1637,7 +1895,7 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
continue; continue;
} }
while (inb(tmport) != 0x8e); while (inb(tmport) != 0x8e);
dev->active_idu |= m; dev->active_id[0] |= m;
tmport = wkport + 0x50; tmport = wkport + 0x50;
outb(0x30, tmport); outb(0x30, tmport);
...@@ -1667,7 +1925,7 @@ static void is880(struct Scsi_Host *host, unsigned int wkport) ...@@ -1667,7 +1925,7 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
tmport += 0x07; tmport += 0x07;
outb(0, tmport); outb(0, tmport);
tmport += 0x02; tmport += 0x02;
outb(dev->id[i].devspu, tmport++); outb(dev->id[0][i].devsp, tmport++);
outb(0, tmport++); outb(0, tmport++);
outb(inqd[6], tmport++); outb(inqd[6], tmport++);
outb(inqd[7], tmport++); outb(inqd[7], tmport++);
...@@ -1719,19 +1977,19 @@ static void is880(struct Scsi_Host *host, unsigned int wkport) ...@@ -1719,19 +1977,19 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
inq_ok: inq_ok:
mbuf[36] = 0; mbuf[36] = 0;
printk(KERN_INFO " ID: %2d %s\n", i, &mbuf[8]); printk(KERN_INFO " ID: %2d %s\n", i, &mbuf[8]);
dev->id[i].devtypeu = mbuf[0]; dev->id[0][i].devtype = mbuf[0];
rmb = mbuf[1]; rmb = mbuf[1];
n = mbuf[7]; n = mbuf[7];
if ((mbuf[7] & 0x60) == 0) { if ((mbuf[7] & 0x60) == 0) {
goto not_wide; goto not_wide;
} }
if ((i < 8) && ((dev->global_map & 0x20) == 0)) { if ((i < 8) && ((dev->global_map[0] & 0x20) == 0)) {
goto not_wide; goto not_wide;
} }
if (lvdmode == 0) { if (lvdmode == 0) {
goto chg_wide; goto chg_wide;
} }
if (dev->sp[i] != 0x04) // force u2 if (dev->sp[0][i] != 0x04) // force u2
{ {
goto chg_wide; goto chg_wide;
} }
...@@ -1748,7 +2006,7 @@ static void is880(struct Scsi_Host *host, unsigned int wkport) ...@@ -1748,7 +2006,7 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
tmport += 0x06; tmport += 0x06;
outb(0, tmport); outb(0, tmport);
tmport += 0x02; tmport += 0x02;
outb(dev->id[i].devspu, tmport++); outb(dev->id[0][i].devsp, tmport++);
outb(0, tmport++); outb(0, tmport++);
outb(satn[6], tmport++); outb(satn[6], tmport++);
outb(satn[7], tmport++); outb(satn[7], tmport++);
...@@ -1872,8 +2130,8 @@ static void is880(struct Scsi_Host *host, unsigned int wkport) ...@@ -1872,8 +2130,8 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
if (mbuf[3] == 0x09) { if (mbuf[3] == 0x09) {
m = 1; m = 1;
m = m << i; m = m << i;
dev->wide_idu |= m; dev->wide_id[0] |= m;
dev->id[i].devspu = 0xce; dev->id[0][i].devsp = 0xce;
continue; continue;
} }
chg_wide: chg_wide:
...@@ -1889,7 +2147,7 @@ static void is880(struct Scsi_Host *host, unsigned int wkport) ...@@ -1889,7 +2147,7 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
tmport += 0x06; tmport += 0x06;
outb(0, tmport); outb(0, tmport);
tmport += 0x02; tmport += 0x02;
outb(dev->id[i].devspu, tmport++); outb(dev->id[0][i].devsp, tmport++);
outb(0, tmport++); outb(0, tmport++);
outb(satn[6], tmport++); outb(satn[6], tmport++);
outb(satn[7], tmport++); outb(satn[7], tmport++);
...@@ -2015,29 +2273,29 @@ static void is880(struct Scsi_Host *host, unsigned int wkport) ...@@ -2015,29 +2273,29 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
} }
m = 1; m = 1;
m = m << i; m = m << i;
dev->wide_idu |= m; dev->wide_id[0] |= m;
not_wide: not_wide:
if ((dev->id[i].devtypeu == 0x00) || (dev->id[i].devtypeu == 0x07) || ((dev->id[i].devtypeu == 0x05) && ((n & 0x10) != 0))) { if ((dev->id[0][i].devtype == 0x00) || (dev->id[0][i].devtype == 0x07) || ((dev->id[0][i].devtype == 0x05) && ((n & 0x10) != 0))) {
m = 1; m = 1;
m = m << i; m = m << i;
if ((dev->async & m) != 0) { if ((dev->async[0] & m) != 0) {
goto set_sync; goto set_sync;
} }
} }
continue; continue;
set_sync: set_sync:
if (dev->sp[i] == 0x02) { if (dev->sp[0][i] == 0x02) {
synu[4] = 0x0c; synu[4] = 0x0c;
synuw[4] = 0x0c; synuw[4] = 0x0c;
} else { } else {
if (dev->sp[i] >= 0x03) { if (dev->sp[0][i] >= 0x03) {
synu[4] = 0x0a; synu[4] = 0x0a;
synuw[4] = 0x0a; synuw[4] = 0x0a;
} }
} }
tmport = wkport + 0x5b; tmport = wkport + 0x5b;
j = 0; j = 0;
if ((m & dev->wide_idu) != 0) { if ((m & dev->wide_id[0]) != 0) {
j |= 0x01; j |= 0x01;
} }
outb(j, tmport); outb(j, tmport);
...@@ -2051,7 +2309,7 @@ static void is880(struct Scsi_Host *host, unsigned int wkport) ...@@ -2051,7 +2309,7 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
tmport += 0x06; tmport += 0x06;
outb(0, tmport); outb(0, tmport);
tmport += 0x02; tmport += 0x02;
outb(dev->id[i].devspu, tmport++); outb(dev->id[0][i].devsp, tmport++);
outb(0, tmport++); outb(0, tmport++);
outb(satn[6], tmport++); outb(satn[6], tmport++);
outb(satn[7], tmport++); outb(satn[7], tmport++);
...@@ -2076,14 +2334,14 @@ static void is880(struct Scsi_Host *host, unsigned int wkport) ...@@ -2076,14 +2334,14 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
while ((inb(tmport) & 0x80) == 0) { while ((inb(tmport) & 0x80) == 0) {
if ((inb(tmport) & 0x01) != 0) { if ((inb(tmport) & 0x01) != 0) {
tmport -= 0x06; tmport -= 0x06;
if ((m & dev->wide_idu) != 0) { if ((m & dev->wide_id[0]) != 0) {
if ((m & dev->ultra_map) != 0) { if ((m & dev->ultra_map[0]) != 0) {
outb(synuw[j++], tmport); outb(synuw[j++], tmport);
} else { } else {
outb(synw[j++], tmport); outb(synw[j++], tmport);
} }
} else { } else {
if ((m & dev->ultra_map) != 0) { if ((m & dev->ultra_map[0]) != 0) {
outb(synu[j++], tmport); outb(synu[j++], tmport);
} else { } else {
outb(synn[j++], tmport); outb(synn[j++], tmport);
...@@ -2197,7 +2455,7 @@ static void is880(struct Scsi_Host *host, unsigned int wkport) ...@@ -2197,7 +2455,7 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
if (mbuf[4] > 0x0e) { if (mbuf[4] > 0x0e) {
mbuf[4] = 0x0e; mbuf[4] = 0x0e;
} }
dev->id[i].devspu = mbuf[4]; dev->id[0][i].devsp = mbuf[4];
if (mbuf[3] < 0x0c) { if (mbuf[3] < 0x0c) {
j = 0xb0; j = 0xb0;
goto set_syn_ok; goto set_syn_ok;
...@@ -2220,249 +2478,179 @@ static void is880(struct Scsi_Host *host, unsigned int wkport) ...@@ -2220,249 +2478,179 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
} }
j = 0x60; j = 0x60;
set_syn_ok: set_syn_ok:
dev->id[i].devspu = (dev->id[i].devspu & 0x0f) | j; dev->id[0][i].devsp = (dev->id[0][i].devsp & 0x0f) | j;
} }
} }
static void atp870u_free_tables(struct Scsi_Host *host) static void atp870u_free_tables(struct Scsi_Host *host)
{ {
struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata; struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata;
int k; int j, k;
for (j=0; j < 2; j++) {
for (k = 0; k < 16; k++) { for (k = 0; k < 16; k++) {
if (!atp_dev->id[k].prd_tableu) if (!atp_dev->id[j][k].prd_table)
continue; continue;
pci_free_consistent(atp_dev->pdev, 1024, atp_dev->id[k].prd_tableu, pci_free_consistent(atp_dev->pdev, 1024, atp_dev->id[j][k].prd_table, atp_dev->id[j][k].prdaddr);
atp_dev->id[k].prd_phys); atp_dev->id[j][k].prd_table = NULL;
atp_dev->id[k].prd_tableu = NULL; }
} }
} }
static int atp870u_init_tables(struct Scsi_Host *host) static int atp870u_init_tables(struct Scsi_Host *host)
{ {
struct atp_unit *dev = (struct atp_unit *)&host->hostdata; struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata;
int k, i; int c,k;
for(c=0;c < 2;c++) {
for (i = k = 0; k < 16; k++) { for(k=0;k<16;k++) {
dev->id[k].prd_tableu = pci_alloc_consistent(dev->pdev, 1024, &dev->id[k].prd_phys); atp_dev->id[c][k].prd_table = pci_alloc_consistent(atp_dev->pdev, 1024, &(atp_dev->id[c][k].prdaddr));
if (!dev->id[k].prd_tableu) { if (!atp_dev->id[c][k].prd_table) {
atp870u_free_tables(host); printk("atp870u_init_tables fail\n");
return -ENOMEM; atp870u_free_tables(host);
} return -ENOMEM;
dev->id[k].devspu = 0x20; }
dev->id[k].devtypeu = 0; atp_dev->id[c][k].devsp=0x20;
dev->id[k].curr_req = NULL; atp_dev->id[c][k].devtype = 0x7f;
} atp_dev->id[c][k].curr_req = NULL;
dev->active_idu = 0; }
dev->wide_idu = 0;
dev->host_idu = 0x07; atp_dev->active_id[c] = 0;
dev->quhdu = 0; atp_dev->wide_id[c] = 0;
dev->quendu = 0; atp_dev->host_id[c] = 0x07;
dev->chip_veru = 0; atp_dev->quhd[c] = 0;
dev->last_cmd = 0xff; atp_dev->quend[c] = 0;
dev->in_snd = 0; atp_dev->last_cmd[c] = 0xff;
dev->in_int = 0; atp_dev->in_snd[c] = 0;
for (k = 0; k < qcnt; k++) { atp_dev->in_int[c] = 0;
dev->querequ[k] = NULL;
} for (k = 0; k < qcnt; k++) {
for (k = 0; k < 16; k++) { atp_dev->quereq[c][k] = NULL;
dev->id[k].curr_req = NULL; }
dev->sp[k] = 0x04; for (k = 0; k < 16; k++) {
atp_dev->id[c][k].curr_req = NULL;
atp_dev->sp[c][k] = 0x04;
}
} }
return 0; return 0;
} }
/* return non-zero on detection */ /* return non-zero on detection */
static int atp870u_probe(struct pci_dev *dev, const struct pci_device_id *ent) static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{ {
unsigned char k, m; unsigned char k, m, c;
unsigned long flags; unsigned long flags;
unsigned int base_io, error, tmport; unsigned int base_io, tmport, error,n;
unsigned char host_id; unsigned char host_id;
unsigned short n; struct Scsi_Host *shpnt = NULL;
struct Scsi_Host *shpnt;
struct atp_unit atp_dev, *p; struct atp_unit atp_dev, *p;
static int count; unsigned char setupdata[2][16];
int count = 0;
if (pci_enable_device(dev))
if (pci_enable_device(pdev))
return -EIO; return -EIO;
if (pci_set_dma_mask(dev, 0xFFFFFFFFUL)) { if (!pci_set_dma_mask(pdev, 0xFFFFFFUL)) {
printk(KERN_ERR "atp870u: 32bit DMA mask required but not available.\n"); printk(KERN_INFO "atp870u: use 32bit DMA mask.\n");
return -EIO; } else {
} printk(KERN_ERR "atp870u: DMA mask required but not available.\n");
return -EIO;
}
memset(&atp_dev, 0, sizeof atp_dev); memset(&atp_dev, 0, sizeof atp_dev);
/* /*
* It's probably easier to weed out some revisions like * It's probably easier to weed out some revisions like
* this than via the PCI device table * this than via the PCI device table
*/ */
if (ent->device == PCI_DEVICE_ID_ARTOP_AEC7610) { if (ent->device == PCI_DEVICE_ID_ARTOP_AEC7610) {
error = pci_read_config_byte(dev, PCI_CLASS_REVISION, &atp_dev.chip_veru); error = pci_read_config_byte(pdev, PCI_CLASS_REVISION, &atp_dev.chip_ver);
if (atp_dev.chip_veru < 2) if (atp_dev.chip_ver < 2)
return -EIO; return -EIO;
} }
switch (ent->device) { switch (ent->device) {
case 0x8081:
case PCI_DEVICE_ID_ARTOP_AEC7612UW: case PCI_DEVICE_ID_ARTOP_AEC7612UW:
case PCI_DEVICE_ID_ARTOP_AEC7612SUW: case PCI_DEVICE_ID_ARTOP_AEC7612SUW:
atp_dev.chip_veru = 0x04; case ATP880_DEVID1:
case ATP880_DEVID2:
case ATP885_DEVID:
atp_dev.chip_ver = 0x04;
default: default:
break; break;
} }
base_io = pci_resource_start(pdev, 0);
base_io &= 0xfffffff8;
if ((ent->device == ATP880_DEVID1)||(ent->device == ATP880_DEVID2)) {
error = pci_read_config_byte(pdev, PCI_CLASS_REVISION, &atp_dev.chip_ver);
pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80);//JCC082803
base_io = pci_resource_start(dev, 0);
if (ent->device != 0x8081) {
error = pci_read_config_byte(dev, 0x49, &host_id);
base_io &= 0xfffffff8;
printk(KERN_INFO " ACARD AEC-671X PCI Ultra/W SCSI-3 Host Adapter: %d "
"IO:%x, IRQ:%d.\n", count, base_io, dev->irq);
atp_dev.unit = count;
atp_dev.ioport = base_io;
atp_dev.pciport = base_io + 0x20;
atp_dev.deviceid = ent->device;
host_id &= 0x07;
atp_dev.host_idu = host_id;
tmport = base_io + 0x22;
atp_dev.scam_on = inb(tmport);
tmport += 0x0b;
atp_dev.global_map = inb(tmport++);
atp_dev.ultra_map = inw(tmport);
if (atp_dev.ultra_map == 0) {
atp_dev.scam_on = 0x00;
atp_dev.global_map = 0x20;
atp_dev.ultra_map = 0xffff;
}
shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
if (!shpnt)
return -ENOMEM;
p = (struct atp_unit *)&shpnt->hostdata;
atp_dev.host = shpnt;
atp_dev.pdev = dev;
pci_set_drvdata(dev, p);
memcpy(p, &atp_dev, sizeof atp_dev);
if (atp870u_init_tables(shpnt) < 0)
goto unregister;
if (request_irq(dev->irq, atp870u_intr_handle, SA_SHIRQ, "atp870u", shpnt)) {
printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", dev->irq);
goto free_tables;
}
spin_lock_irqsave(shpnt->host_lock, flags);
if (atp_dev.chip_veru > 0x07) { /* check if atp876 chip then enable terminator */
tmport = base_io + 0x3e;
outb(0x00, tmport);
}
tmport = base_io + 0x3a;
k = (inb(tmport) & 0xf3) | 0x10;
outb(k, tmport);
outb((k & 0xdf), tmport);
mdelay(32);
outb(k, tmport);
mdelay(32);
tmport = base_io;
outb((host_id | 0x08), tmport);
tmport += 0x18;
outb(0, tmport);
tmport += 0x07;
while ((inb(tmport) & 0x80) == 0)
mdelay(1);
tmport -= 0x08;
inb(tmport);
tmport = base_io + 1;
outb(8, tmport++);
outb(0x7f, tmport);
tmport = base_io + 0x11;
outb(0x20, tmport);
tscam(shpnt);
is870(shpnt, base_io);
tmport = base_io + 0x3a;
outb((inb(tmport) & 0xef), tmport);
tmport++;
outb((inb(tmport) | 0x20), tmport);
} else {
base_io &= 0xfffffff8;
host_id = inb(base_io + 0x39); host_id = inb(base_io + 0x39);
host_id >>= 0x04; host_id >>= 0x04;
printk(KERN_INFO " ACARD AEC-67160 PCI Ultra3 LVD Host Adapter: %d" printk(KERN_INFO " ACARD AEC-67160 PCI Ultra3 LVD Host Adapter: %d"
" IO:%x, IRQ:%d.\n", count, base_io, dev->irq); " IO:%x, IRQ:%d.\n", count, base_io, pdev->irq);
atp_dev.ioport = base_io + 0x40; atp_dev.ioport[0] = base_io + 0x40;
atp_dev.pciport = base_io + 0x28; atp_dev.pciport[0] = base_io + 0x28;
atp_dev.deviceid = ent->device; atp_dev.dev_id = ent->device;
atp_dev.host_idu = host_id; atp_dev.host_id[0] = host_id;
tmport = base_io + 0x22; tmport = base_io + 0x22;
atp_dev.scam_on = inb(tmport); atp_dev.scam_on = inb(tmport);
tmport += 0x13; tmport += 0x13;
atp_dev.global_map = inb(tmport); atp_dev.global_map[0] = inb(tmport);
tmport += 0x07; tmport += 0x07;
atp_dev.ultra_map = inw(tmport); atp_dev.ultra_map[0] = inw(tmport);
n = 0x3f09; n = 0x3f09;
next_fblk: next_fblk_880:
if (n >= 0x4000) if (n >= 0x4000)
goto flash_ok; goto flash_ok_880;
m = 0; m = 0;
outw(n, base_io + 0x34); outw(n, base_io + 0x34);
n += 0x0002; n += 0x0002;
if (inb(base_io + 0x30) == 0xff) if (inb(base_io + 0x30) == 0xff)
goto flash_ok; goto flash_ok_880;
atp_dev.sp[m++] = inb(base_io + 0x30); atp_dev.sp[0][m++] = inb(base_io + 0x30);
atp_dev.sp[m++] = inb(base_io + 0x31); atp_dev.sp[0][m++] = inb(base_io + 0x31);
atp_dev.sp[m++] = inb(base_io + 0x32); atp_dev.sp[0][m++] = inb(base_io + 0x32);
atp_dev.sp[m++] = inb(base_io + 0x33); atp_dev.sp[0][m++] = inb(base_io + 0x33);
outw(n, base_io + 0x34); outw(n, base_io + 0x34);
n += 0x0002; n += 0x0002;
atp_dev.sp[m++] = inb(base_io + 0x30); atp_dev.sp[0][m++] = inb(base_io + 0x30);
atp_dev.sp[m++] = inb(base_io + 0x31); atp_dev.sp[0][m++] = inb(base_io + 0x31);
atp_dev.sp[m++] = inb(base_io + 0x32); atp_dev.sp[0][m++] = inb(base_io + 0x32);
atp_dev.sp[m++] = inb(base_io + 0x33); atp_dev.sp[0][m++] = inb(base_io + 0x33);
outw(n, base_io + 0x34); outw(n, base_io + 0x34);
n += 0x0002; n += 0x0002;
atp_dev.sp[m++] = inb(base_io + 0x30); atp_dev.sp[0][m++] = inb(base_io + 0x30);
atp_dev.sp[m++] = inb(base_io + 0x31); atp_dev.sp[0][m++] = inb(base_io + 0x31);
atp_dev.sp[m++] = inb(base_io + 0x32); atp_dev.sp[0][m++] = inb(base_io + 0x32);
atp_dev.sp[m++] = inb(base_io + 0x33); atp_dev.sp[0][m++] = inb(base_io + 0x33);
outw(n, base_io + 0x34); outw(n, base_io + 0x34);
n += 0x0002; n += 0x0002;
atp_dev.sp[m++] = inb(base_io + 0x30); atp_dev.sp[0][m++] = inb(base_io + 0x30);
atp_dev.sp[m++] = inb(base_io + 0x31); atp_dev.sp[0][m++] = inb(base_io + 0x31);
atp_dev.sp[m++] = inb(base_io + 0x32); atp_dev.sp[0][m++] = inb(base_io + 0x32);
atp_dev.sp[m++] = inb(base_io + 0x33); atp_dev.sp[0][m++] = inb(base_io + 0x33);
n += 0x0018; n += 0x0018;
goto next_fblk; goto next_fblk_880;
flash_ok: flash_ok_880:
outw(0, base_io + 0x34); outw(0, base_io + 0x34);
atp_dev.ultra_map = 0; atp_dev.ultra_map[0] = 0;
atp_dev.async = 0; atp_dev.async[0] = 0;
for (k = 0; k < 16; k++) { for (k = 0; k < 16; k++) {
n = 1; n = 1;
n = n << k; n = n << k;
if (atp_dev.sp[k] > 1) { if (atp_dev.sp[0][k] > 1) {
atp_dev.ultra_map |= n; atp_dev.ultra_map[0] |= n;
} else { } else {
if (atp_dev.sp[k] == 0) if (atp_dev.sp[0][k] == 0)
atp_dev.async |= n; atp_dev.async[0] |= n;
} }
} }
atp_dev.async = ~(atp_dev.async); atp_dev.async[0] = ~(atp_dev.async[0]);
outb(atp_dev.global_map, base_io + 0x35); outb(atp_dev.global_map[0], base_io + 0x35);
shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit)); shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
if (!shpnt) if (!shpnt)
...@@ -2471,16 +2659,16 @@ static int atp870u_probe(struct pci_dev *dev, const struct pci_device_id *ent) ...@@ -2471,16 +2659,16 @@ static int atp870u_probe(struct pci_dev *dev, const struct pci_device_id *ent)
p = (struct atp_unit *)&shpnt->hostdata; p = (struct atp_unit *)&shpnt->hostdata;
atp_dev.host = shpnt; atp_dev.host = shpnt;
atp_dev.pdev = dev; atp_dev.pdev = pdev;
pci_set_drvdata(dev, p); pci_set_drvdata(pdev, p);
memcpy(p, &atp_dev, sizeof atp_dev); memcpy(p, &atp_dev, sizeof atp_dev);
if (atp870u_init_tables(shpnt) < 0) { if (atp870u_init_tables(shpnt) < 0) {
printk(KERN_ERR "Unable to allocate tables for Acard controller\n"); printk(KERN_ERR "Unable to allocate tables for Acard controller\n");
goto unregister; goto unregister;
} }
if (request_irq(dev->irq, atp870u_intr_handle, SA_SHIRQ, "atp870u", shpnt)) { if (request_irq(pdev->irq, atp870u_intr_handle, SA_SHIRQ, "atp880i", shpnt)) {
printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", dev->irq); printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", pdev->irq);
goto free_tables; goto free_tables;
} }
...@@ -2513,96 +2701,354 @@ static int atp870u_probe(struct pci_dev *dev, const struct pci_device_id *ent) ...@@ -2513,96 +2701,354 @@ static int atp870u_probe(struct pci_dev *dev, const struct pci_device_id *ent)
outb(0x20, tmport); outb(0x20, tmport);
tscam(shpnt); tscam(shpnt);
is880(shpnt, base_io); is880(p, base_io);
tmport = base_io + 0x38; tmport = base_io + 0x38;
outb(0xb0, tmport); outb(0xb0, tmport);
}
if (p->chip_veru == 4)
shpnt->max_id = 16; shpnt->max_id = 16;
shpnt->this_id = host_id;
shpnt->this_id = host_id; shpnt->unique_id = base_io;
shpnt->unique_id = base_io; shpnt->io_port = base_io;
shpnt->io_port = base_io;
if (ent->device == 0x8081) {
shpnt->n_io_port = 0x60; /* Number of bytes of I/O space used */ shpnt->n_io_port = 0x60; /* Number of bytes of I/O space used */
shpnt->irq = pdev->irq;
} else if (ent->device == ATP885_DEVID) {
printk(KERN_INFO " ACARD AEC-67162 PCI Ultra3 LVD Host Adapter: IO:%x, IRQ:%d.\n"
, base_io, pdev->irq);
atp_dev.pdev = pdev;
atp_dev.dev_id = ent->device;
atp_dev.baseport = base_io;
atp_dev.ioport[0] = base_io + 0x80;
atp_dev.ioport[1] = base_io + 0xc0;
atp_dev.pciport[0] = base_io + 0x40;
atp_dev.pciport[1] = base_io + 0x50;
shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
if (!shpnt)
return -ENOMEM;
p = (struct atp_unit *)&shpnt->hostdata;
atp_dev.host = shpnt;
atp_dev.pdev = pdev;
pci_set_drvdata(pdev, p);
memcpy(p, &atp_dev, sizeof(struct atp_unit));
if (atp870u_init_tables(shpnt) < 0)
goto unregister;
#ifdef ED_DBGP
printk("request_irq() shpnt %p hostdata %p\n", shpnt, p);
#endif
if (request_irq(pdev->irq, atp870u_intr_handle, SA_SHIRQ, "atp870u", shpnt)) {
printk(KERN_ERR "Unable to allocate IRQ for Acard controller.\n");
goto free_tables;
}
spin_lock_irqsave(shpnt->host_lock, flags);
c=inb(base_io + 0x29);
outb((c | 0x04),base_io + 0x29);
n=0x1f80;
next_fblk_885:
if (n >= 0x2000) {
goto flash_ok_885;
}
outw(n,base_io + 0x3c);
if (inl(base_io + 0x38) == 0xffffffff) {
goto flash_ok_885;
}
for (m=0; m < 2; m++) {
p->global_map[m]= 0;
for (k=0; k < 4; k++) {
outw(n++,base_io + 0x3c);
((unsigned long *)&setupdata[m][0])[k]=inl(base_io + 0x38);
}
for (k=0; k < 4; k++) {
outw(n++,base_io + 0x3c);
((unsigned long *)&p->sp[m][0])[k]=inl(base_io + 0x38);
}
n += 8;
}
goto next_fblk_885;
flash_ok_885:
#ifdef ED_DBGP
printk( "Flash Read OK\n");
#endif
c=inb(base_io + 0x29);
outb((c & 0xfb),base_io + 0x29);
for (c=0;c < 2;c++) {
p->ultra_map[c]=0;
p->async[c] = 0;
for (k=0; k < 16; k++) {
n=1;
n = n << k;
if (p->sp[c][k] > 1) {
p->ultra_map[c] |= n;
} else {
if (p->sp[c][k] == 0) {
p->async[c] |= n;
}
}
}
p->async[c] = ~(p->async[c]);
if (p->global_map[c] == 0) {
k=setupdata[c][1];
if ((k & 0x40) != 0)
p->global_map[c] |= 0x20;
k &= 0x07;
p->global_map[c] |= k;
if ((setupdata[c][2] & 0x04) != 0)
p->global_map[c] |= 0x08;
p->host_id[c] = setupdata[c][0] & 0x07;
}
}
k = inb(base_io + 0x28) & 0x8f;
k |= 0x10;
outb(k, base_io + 0x28);
outb(0x80, base_io + 0x41);
outb(0x80, base_io + 0x51);
mdelay(100);
outb(0, base_io + 0x41);
outb(0, base_io + 0x51);
mdelay(1000);
inb(base_io + 0x9b);
inb(base_io + 0x97);
inb(base_io + 0xdb);
inb(base_io + 0xd7);
tmport = base_io + 0x80;
k=p->host_id[0];
if (k > 7)
k = (k & 0x07) | 0x40;
k |= 0x08;
outb(k, tmport);
tmport += 0x18;
outb(0, tmport);
tmport += 0x07;
while ((inb(tmport) & 0x80) == 0);
tmport -= 0x08;
inb(tmport);
tmport = base_io + 0x81;
outb(8, tmport++);
outb(0x7f, tmport);
tmport = base_io + 0x91;
outb(0x20, tmport);
tmport = base_io + 0xc0;
k=p->host_id[1];
if (k > 7)
k = (k & 0x07) | 0x40;
k |= 0x08;
outb(k, tmport);
tmport += 0x18;
outb(0, tmport);
tmport += 0x07;
while ((inb(tmport) & 0x80) == 0);
tmport -= 0x08;
inb(tmport);
tmport = base_io + 0xc1;
outb(8, tmport++);
outb(0x7f, tmport);
tmport = base_io + 0xd1;
outb(0x20, tmport);
tscam_885();
printk(KERN_INFO " Scanning Channel A SCSI Device ...\n");
is885(p, base_io + 0x80, 0);
printk(KERN_INFO " Scanning Channel B SCSI Device ...\n");
is885(p, base_io + 0xc0, 1);
k = inb(base_io + 0x28) & 0xcf;
k |= 0xc0;
outb(k, base_io + 0x28);
k = inb(base_io + 0x1f) | 0x80;
outb(k, base_io + 0x1f);
k = inb(base_io + 0x29) | 0x01;
outb(k, base_io + 0x29);
#ifdef ED_DBGP
//printk("atp885: atp_host[0] 0x%p\n", atp_host[0]);
#endif
shpnt->max_id = 16;
shpnt->max_lun = (p->global_map[0] & 0x07) + 1;
shpnt->max_channel = 1;
shpnt->this_id = p->host_id[0];
shpnt->unique_id = base_io;
shpnt->io_port = base_io;
shpnt->n_io_port = 0xff; /* Number of bytes of I/O space used */
shpnt->irq = pdev->irq;
} else { } else {
shpnt->n_io_port = 0x40; /* Number of bytes of I/O space used */ error = pci_read_config_byte(pdev, 0x49, &host_id);
}
shpnt->irq = dev->irq;
spin_unlock_irqrestore(shpnt->host_lock, flags);
if (ent->device == 0x8081) {
if (!request_region(base_io, 0x60, "atp870u"))
goto request_io_fail;
} else {
if (!request_region(base_io, 0x40, "atp870u"))
goto request_io_fail;
}
count++; printk(KERN_INFO " ACARD AEC-671X PCI Ultra/W SCSI-2/3 Host Adapter: %d "
if (scsi_add_host(shpnt, &dev->dev)) "IO:%x, IRQ:%d.\n", count, base_io, pdev->irq);
goto scsi_add_fail;
scsi_scan_host(shpnt); atp_dev.ioport[0] = base_io;
return 0; atp_dev.pciport[0] = base_io + 0x20;
atp_dev.dev_id = ent->device;
scsi_add_fail: host_id &= 0x07;
if (ent->device == 0x8081) atp_dev.host_id[0] = host_id;
release_region(base_io, 0x60); tmport = base_io + 0x22;
else atp_dev.scam_on = inb(tmport);
tmport += 0x0b;
atp_dev.global_map[0] = inb(tmport++);
atp_dev.ultra_map[0] = inw(tmport);
if (atp_dev.ultra_map[0] == 0) {
atp_dev.scam_on = 0x00;
atp_dev.global_map[0] = 0x20;
atp_dev.ultra_map[0] = 0xffff;
}
shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
if (!shpnt)
return -ENOMEM;
p = (struct atp_unit *)&shpnt->hostdata;
atp_dev.host = shpnt;
atp_dev.pdev = pdev;
pci_set_drvdata(pdev, p);
memcpy(p, &atp_dev, sizeof atp_dev);
if (atp870u_init_tables(shpnt) < 0)
goto unregister;
if (request_irq(pdev->irq, atp870u_intr_handle, SA_SHIRQ, "atp870i", shpnt)) {
printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", pdev->irq);
goto free_tables;
}
spin_lock_irqsave(shpnt->host_lock, flags);
if (atp_dev.chip_ver > 0x07) { /* check if atp876 chip then enable terminator */
tmport = base_io + 0x3e;
outb(0x00, tmport);
}
tmport = base_io + 0x3a;
k = (inb(tmport) & 0xf3) | 0x10;
outb(k, tmport);
outb((k & 0xdf), tmport);
mdelay(32);
outb(k, tmport);
mdelay(32);
tmport = base_io;
outb((host_id | 0x08), tmport);
tmport += 0x18;
outb(0, tmport);
tmport += 0x07;
while ((inb(tmport) & 0x80) == 0)
mdelay(1);
tmport -= 0x08;
inb(tmport);
tmport = base_io + 1;
outb(8, tmport++);
outb(0x7f, tmport);
tmport = base_io + 0x11;
outb(0x20, tmport);
tscam(shpnt);
is870(p, base_io);
tmport = base_io + 0x3a;
outb((inb(tmport) & 0xef), tmport);
tmport++;
outb((inb(tmport) | 0x20), tmport);
if (atp_dev.chip_ver == 4)
shpnt->max_id = 16;
else
shpnt->max_id = 7;
shpnt->this_id = host_id;
shpnt->unique_id = base_io;
shpnt->io_port = base_io;
shpnt->n_io_port = 0x40; /* Number of bytes of I/O space used */
shpnt->irq = pdev->irq;
}
spin_unlock_irqrestore(shpnt->host_lock, flags);
if(ent->device==ATP885_DEVID) {
if(!request_region(base_io, 0xff, "atp870u")) /* Register the IO ports that we use */
goto request_io_fail;
} else if((ent->device==ATP880_DEVID1)||(ent->device==ATP880_DEVID2)) {
if(!request_region(base_io, 0x60, "atp870u")) /* Register the IO ports that we use */
goto request_io_fail;
} else {
if(!request_region(base_io, 0x40, "atp870u")) /* Register the IO ports that we use */
goto request_io_fail;
}
count++;
if (scsi_add_host(shpnt, &pdev->dev))
goto scsi_add_fail;
scsi_scan_host(shpnt);
#ifdef ED_DBGP
printk("atp870u_prob : exit\n");
#endif
return 0;
scsi_add_fail:
printk("atp870u_prob:scsi_add_fail\n");
if(ent->device==ATP885_DEVID) {
release_region(base_io, 0xff);
} else if((ent->device==ATP880_DEVID1)||(ent->device==ATP880_DEVID2)) {
release_region(base_io, 0x60);
} else {
release_region(base_io, 0x40); release_region(base_io, 0x40);
}
request_io_fail: request_io_fail:
free_irq(dev->irq, shpnt); printk("atp870u_prob:request_io_fail\n");
free_irq(pdev->irq, shpnt);
free_tables: free_tables:
printk("atp870u_prob:free_table\n");
atp870u_free_tables(shpnt); atp870u_free_tables(shpnt);
unregister: unregister:
printk("atp870u_prob:unregister\n");
scsi_host_put(shpnt); scsi_host_put(shpnt);
return -1; return -1;
} }
/* The abort command does not leave the device in a clean state where /* 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 it is available to be used again. Until this gets worked out, we will
leave it commented out. */ leave it commented out. */
static int atp870u_abort(struct scsi_cmnd * SCpnt) int atp870u_abort(struct scsi_cmnd * SCpnt)
{ {
unsigned char j, k; unsigned char j, k, c;
struct scsi_cmnd *workrequ; struct scsi_cmnd *workrequ;
unsigned int tmport; unsigned int tmport;
struct atp_unit *dev = (struct atp_unit *)&SCpnt->device->host->hostdata; struct atp_unit *dev;
struct Scsi_Host *host;
host = SCpnt->device->host;
printk(KERN_DEBUG "working=%x last_cmd=%x ", dev->working, dev->last_cmd); dev = (struct atp_unit *)&host->hostdata;
printk(" quhdu=%x quendu=%x ", dev->quhdu, dev->quendu); c=SCpnt->device->channel;
tmport = dev->ioport; printk(" atp870u: abort Channel = %x \n", c);
for (j = 0; j < 0x17; j++) { printk("working=%x last_cmd=%x ", dev->working[c], dev->last_cmd[c]);
printk(" quhdu=%x quendu=%x ", dev->quhd[c], dev->quend[c]);
tmport = dev->ioport[c];
for (j = 0; j < 0x18; j++) {
printk(" r%2x=%2x", j, inb(tmport++)); printk(" r%2x=%2x", j, inb(tmport++));
} }
tmport += 0x05; tmport += 0x04;
printk(" r1c=%2x", inb(tmport)); printk(" r1c=%2x", inb(tmport));
tmport += 0x03; tmport += 0x03;
printk(" r1f=%2x in_snd=%2x ", inb(tmport), dev->in_snd); printk(" r1f=%2x in_snd=%2x ", inb(tmport), dev->in_snd[c]);
tmport = dev->pciport; tmport= dev->pciport[c];
printk(" r20=%2x", inb(tmport)); printk(" d00=%2x", inb(tmport));
tmport += 0x02; tmport += 0x02;
printk(" r22=%2x", inb(tmport)); printk(" d02=%2x", inb(tmport));
tmport = dev->ioport + 0x3a; for(j=0;j<16;j++) {
printk(" r3a=%2x \n", inb(tmport)); if (dev->id[c][j].curr_req != NULL) {
tmport = dev->ioport + 0x3b; workrequ = dev->id[c][j].curr_req;
printk(" r3b=%2x \n", inb(tmport)); printk("\n que cdb= ");
for (j = 0; j < 16; j++) { for (k=0; k < workrequ->cmd_len; k++) {
if (dev->id[j].curr_req != NULL) { printk(" %2x ",workrequ->cmnd[k]);
workrequ = dev->id[j].curr_req;
printk("\n que cdb= ");
for (k = 0; k < workrequ->cmd_len; k++) {
printk(" %2x ", workrequ->cmnd[k]);
}
printk(" last_lenu= %lx ", dev->id[j].last_lenu);
} }
printk(" last_lenu= %x ",(unsigned int)dev->id[c][j].last_len);
}
} }
/* Sort of - the thing handles itself */
return SUCCESS; return SUCCESS;
} }
static const char *atp870u_info(struct Scsi_Host *notused) const char *atp870u_info(struct Scsi_Host *notused)
{ {
static char buffer[128]; static char buffer[128];
...@@ -2611,17 +3057,21 @@ static const char *atp870u_info(struct Scsi_Host *notused) ...@@ -2611,17 +3057,21 @@ static const char *atp870u_info(struct Scsi_Host *notused)
return buffer; return buffer;
} }
int atp870u_set_info(char *buffer, int length, struct Scsi_Host *HBAptr)
{
return -ENOSYS; /* Currently this is a no-op */
}
#define BLS buffer + len + size #define BLS buffer + len + size
static int atp870u_proc_info(struct Scsi_Host *HBAptr, char *buffer, int atp870u_proc_info(struct Scsi_Host *HBAptr, char *buffer, char **start, off_t offset, int length, int inout)
char **start, off_t offset, int length, int inout)
{ {
static u8 buff[512]; static u8 buff[512];
int size = 0; int size = 0;
int len = 0; int len = 0;
off_t begin = 0; off_t begin = 0;
off_t pos = 0; off_t pos = 0;
if (inout) if (inout)
return -ENOSYS; return -ENOSYS;
if (offset == 0) { if (offset == 0) {
memset(buff, 0, sizeof(buff)); memset(buff, 0, sizeof(buff));
...@@ -2637,7 +3087,7 @@ static int atp870u_proc_info(struct Scsi_Host *HBAptr, char *buffer, ...@@ -2637,7 +3087,7 @@ static int atp870u_proc_info(struct Scsi_Host *HBAptr, char *buffer,
size += sprintf(BLS, " IRQ: %d\n", HBAptr->irq); size += sprintf(BLS, " IRQ: %d\n", HBAptr->irq);
len += size; len += size;
pos = begin + len; pos = begin + len;
*start = buffer + (offset - begin); /* Start of wanted data */ *start = buffer + (offset - begin); /* Start of wanted data */
len -= (offset - begin); /* Start slop */ len -= (offset - begin); /* Start slop */
if (len > length) { if (len > length) {
...@@ -2646,15 +3096,15 @@ static int atp870u_proc_info(struct Scsi_Host *HBAptr, char *buffer, ...@@ -2646,15 +3096,15 @@ static int atp870u_proc_info(struct Scsi_Host *HBAptr, char *buffer,
return (len); return (len);
} }
static int atp870u_biosparam(struct scsi_device *sdev,
struct block_device *dev, sector_t capacity, int *ip) static int atp870u_biosparam(struct scsi_device *disk, struct block_device *dev,
sector_t capacity, int *ip)
{ {
int heads, sectors, cylinders; int heads, sectors, cylinders;
heads = 64; heads = 64;
sectors = 32; sectors = 32;
cylinders = (unsigned long)capacity / (heads * sectors); cylinders = (unsigned long)capacity / (heads * sectors);
if (cylinders > 1024) { if (cylinders > 1024) {
heads = 255; heads = 255;
sectors = 63; sectors = 63;
...@@ -2667,39 +3117,46 @@ static int atp870u_biosparam(struct scsi_device *sdev, ...@@ -2667,39 +3117,46 @@ static int atp870u_biosparam(struct scsi_device *sdev,
return 0; return 0;
} }
static void atp870u_remove(struct pci_dev *pdev) static void atp870u_remove (struct pci_dev *pdev)
{ {
struct atp_unit *atp_dev = pci_get_drvdata(pdev); struct atp_unit *devext = pci_get_drvdata(pdev);
struct Scsi_Host *pshost = atp_dev->host; struct Scsi_Host *pshost = devext->host;
scsi_remove_host(pshost); scsi_remove_host(pshost);
printk(KERN_INFO "free_irq : %d\n",pshost->irq);
free_irq(pshost->irq, pshost); free_irq(pshost->irq, pshost);
release_region(pshost->io_port, pshost->n_io_port); release_region(pshost->io_port, pshost->n_io_port);
printk(KERN_INFO "atp870u_free_tables : %p\n",pshost);
atp870u_free_tables(pshost); atp870u_free_tables(pshost);
printk(KERN_INFO "scsi_host_put : %p\n",pshost);
scsi_host_put(pshost); scsi_host_put(pshost);
pci_set_drvdata(pdev, NULL); printk(KERN_INFO "pci_set_drvdata : %p\n",pdev);
pci_set_drvdata(pdev, NULL);
} }
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static struct scsi_host_template atp870u_template = { static struct scsi_host_template atp870u_template = {
.module = THIS_MODULE, .module = THIS_MODULE,
.name = "atp870u", .name = "atp870u" /* name */,
.proc_name = "atp870u", .proc_name = "atp870u",
.proc_info = atp870u_proc_info, .proc_info = atp870u_proc_info,
.info = atp870u_info, .info = atp870u_info /* info */,
.queuecommand = atp870u_queuecommand, .queuecommand = atp870u_queuecommand /* queuecommand */,
.eh_abort_handler = atp870u_abort, .eh_abort_handler = atp870u_abort /* abort */,
.bios_param = atp870u_biosparam, .bios_param = atp870u_biosparam /* biosparm */,
.can_queue = qcnt, .can_queue = qcnt /* can_queue */,
.this_id = 7, .this_id = 7 /* SCSI ID */,
.sg_tablesize = ATP870U_SCATTER, .sg_tablesize = ATP870U_SCATTER /*SG_ALL*/ /*SG_NONE*/,
.cmd_per_lun = ATP870U_CMDLUN, .cmd_per_lun = ATP870U_CMDLUN /* commands per lun */,
.use_clustering = ENABLE_CLUSTERING, .use_clustering = ENABLE_CLUSTERING,
.max_sectors = ATP870U_MAX_SECTORS,
}; };
static struct pci_device_id atp870u_id_table[] = { static struct pci_device_id atp870u_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, 0x8081) }, { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP885_DEVID) },
{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID1) },
{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID2) },
{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7610) }, { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7610) },
{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612UW) }, { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612UW) },
{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612U) }, { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612U) },
...@@ -2712,7 +3169,7 @@ static struct pci_device_id atp870u_id_table[] = { ...@@ -2712,7 +3169,7 @@ static struct pci_device_id atp870u_id_table[] = {
MODULE_DEVICE_TABLE(pci, atp870u_id_table); MODULE_DEVICE_TABLE(pci, atp870u_id_table);
static struct pci_driver atp870u_driver = { static struct pci_driver atp870u_driver = {
.id_table = atp870u_id_table, .id_table = atp870u_id_table,
.name = "atp870u", .name = "atp870u",
.probe = atp870u_probe, .probe = atp870u_probe,
...@@ -2721,14 +3178,688 @@ static struct pci_driver atp870u_driver = { ...@@ -2721,14 +3178,688 @@ static struct pci_driver atp870u_driver = {
static int __init atp870u_init(void) static int __init atp870u_init(void)
{ {
return pci_module_init(&atp870u_driver); #ifdef ED_DBGP
printk("atp870u_init: Entry\n");
#endif
return pci_register_driver(&atp870u_driver);
} }
static void __exit atp870u_exit(void) static void __exit atp870u_exit(void)
{ {
#ifdef ED_DBGP
printk("atp870u_exit: Entry\n");
#endif
pci_unregister_driver(&atp870u_driver); pci_unregister_driver(&atp870u_driver);
} }
void tscam_885(void)
{
unsigned char i;
for (i = 0; i < 0x2; i++) {
mdelay(300);
}
return;
}
void is885(struct atp_unit *dev, unsigned int wkport,unsigned char c)
{
unsigned int tmport;
unsigned char i, j, k, rmb, n, lvdmode;
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 inqd[9] = {0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6};
static unsigned char synn[6] = {0x80, 1, 3, 1, 0x19, 0x0e};
unsigned char synu[6] = {0x80, 1, 3, 1, 0x0a, 0x0e};
static unsigned char synw[6] = {0x80, 1, 3, 1, 0x19, 0x0e};
unsigned char synuw[6] = {0x80, 1, 3, 1, 0x0a, 0x0e};
static unsigned char wide[6] = {0x80, 1, 2, 3, 1, 0};
static unsigned char u3[9] = { 0x80,1,6,4,0x09,00,0x0e,0x01,0x02 };
lvdmode=inb(wkport + 0x1b) >> 7;
for (i = 0; i < 16; i++) {
m = 1;
m = m << i;
if ((m & dev->active_id[c]) != 0) {
continue;
}
if (i == dev->host_id[c]) {
printk(KERN_INFO " ID: %2d Host Adapter\n", dev->host_id[c]);
continue;
}
tmport = wkport + 0x1b;
outb(0x01, tmport);
tmport = wkport + 0x01;
outb(0x08, tmport++);
outb(0x7f, tmport++);
outb(satn[0], tmport++);
outb(satn[1], tmport++);
outb(satn[2], tmport++);
outb(satn[3], tmport++);
outb(satn[4], tmport++);
outb(satn[5], tmport++);
tmport += 0x06;
outb(0, tmport);
tmport += 0x02;
outb(dev->id[c][i].devsp, tmport++);
outb(0, tmport++);
outb(satn[6], tmport++);
outb(satn[7], tmport++);
j = i;
if ((j & 0x08) != 0) {
j = (j & 0x07) | 0x40;
}
outb(j, tmport);
tmport += 0x03;
outb(satn[8], tmport);
tmport += 0x07;
while ((inb(tmport) & 0x80) == 0x00);
tmport -= 0x08;
if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
continue;
}
while (inb(tmport) != 0x8e);
dev->active_id[c] |= m;
tmport = wkport + 0x10;
outb(0x30, tmport);
tmport = wkport + 0x14;
outb(0x00, tmport);
phase_cmd:
tmport = wkport + 0x18;
outb(0x08, tmport);
tmport += 0x07;
while ((inb(tmport) & 0x80) == 0x00);
tmport -= 0x08;
j = inb(tmport);
if (j != 0x16) {
tmport = wkport + 0x10;
outb(0x41, tmport);
goto phase_cmd;
}
sel_ok:
tmport = wkport + 0x03;
outb(inqd[0], tmport++);
outb(inqd[1], tmport++);
outb(inqd[2], tmport++);
outb(inqd[3], tmport++);
outb(inqd[4], tmport++);
outb(inqd[5], tmport);
tmport += 0x07;
outb(0, tmport);
tmport += 0x02;
outb(dev->id[c][i].devsp, tmport++);
outb(0, tmport++);
outb(inqd[6], tmport++);
outb(inqd[7], tmport++);
tmport += 0x03;
outb(inqd[8], tmport);
tmport += 0x07;
while ((inb(tmport) & 0x80) == 0x00);
tmport -= 0x08;
if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
continue;
}
while (inb(tmport) != 0x8e);
tmport = wkport + 0x1b;
outb(0x00, tmport);
tmport = wkport + 0x18;
outb(0x08, tmport);
tmport += 0x07;
j = 0;
rd_inq_data:
k = inb(tmport);
if ((k & 0x01) != 0) {
tmport -= 0x06;
mbuf[j++] = inb(tmport);
tmport += 0x06;
goto rd_inq_data;
}
if ((k & 0x80) == 0) {
goto rd_inq_data;
}
tmport -= 0x08;
j = inb(tmport);
if (j == 0x16) {
goto inq_ok;
}
tmport = wkport + 0x10;
outb(0x46, tmport);
tmport += 0x02;
outb(0, tmport++);
outb(0, tmport++);
outb(0, tmport++);
tmport += 0x03;
outb(0x08, tmport);
tmport += 0x07;
while ((inb(tmport) & 0x80) == 0x00);
tmport -= 0x08;
if (inb(tmport) != 0x16) {
goto sel_ok;
}
inq_ok:
mbuf[36] = 0;
printk( KERN_INFO" ID: %2d %s\n", i, &mbuf[8]);
dev->id[c][i].devtype = mbuf[0];
rmb = mbuf[1];
n = mbuf[7];
if ((mbuf[7] & 0x60) == 0) {
goto not_wide;
}
if ((i < 8) && ((dev->global_map[c] & 0x20) == 0)) {
goto not_wide;
}
if (lvdmode == 0) {
goto chg_wide;
}
if (dev->sp[c][i] != 0x04) { // force u2
goto chg_wide;
}
tmport = wkport + 0x1b;
outb(0x01, tmport);
tmport = wkport + 0x03;
outb(satn[0], tmport++);
outb(satn[1], tmport++);
outb(satn[2], tmport++);
outb(satn[3], tmport++);
outb(satn[4], tmport++);
outb(satn[5], tmport++);
tmport += 0x06;
outb(0, tmport);
tmport += 0x02;
outb(dev->id[c][i].devsp, tmport++);
outb(0, tmport++);
outb(satn[6], tmport++);
outb(satn[7], tmport++);
tmport += 0x03;
outb(satn[8], tmport);
tmport += 0x07;
while ((inb(tmport) & 0x80) == 0x00);
tmport -= 0x08;
if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
continue;
}
while (inb(tmport) != 0x8e);
try_u3:
j = 0;
tmport = wkport + 0x14;
outb(0x09, tmport);
tmport += 0x04;
outb(0x20, tmport);
tmport += 0x07;
while ((inb(tmport) & 0x80) == 0) {
if ((inb(tmport) & 0x01) != 0) {
tmport -= 0x06;
outb(u3[j++], tmport);
tmport += 0x06;
}
}
tmport -= 0x08;
while ((inb(tmport) & 0x80) == 0x00);
j = inb(tmport) & 0x0f;
if (j == 0x0f) {
goto u3p_in;
}
if (j == 0x0a) {
goto u3p_cmd;
}
if (j == 0x0e) {
goto try_u3;
}
continue;
u3p_out:
tmport = wkport + 0x18;
outb(0x20, tmport);
tmport += 0x07;
while ((inb(tmport) & 0x80) == 0) {
if ((inb(tmport) & 0x01) != 0) {
tmport -= 0x06;
outb(0, tmport);
tmport += 0x06;
}
}
tmport -= 0x08;
j = inb(tmport) & 0x0f;
if (j == 0x0f) {
goto u3p_in;
}
if (j == 0x0a) {
goto u3p_cmd;
}
if (j == 0x0e) {
goto u3p_out;
}
continue;
u3p_in:
tmport = wkport + 0x14;
outb(0x09, tmport);
tmport += 0x04;
outb(0x20, tmport);
tmport += 0x07;
k = 0;
u3p_in1:
j = inb(tmport);
if ((j & 0x01) != 0) {
tmport -= 0x06;
mbuf[k++] = inb(tmport);
tmport += 0x06;
goto u3p_in1;
}
if ((j & 0x80) == 0x00) {
goto u3p_in1;
}
tmport -= 0x08;
j = inb(tmport) & 0x0f;
if (j == 0x0f) {
goto u3p_in;
}
if (j == 0x0a) {
goto u3p_cmd;
}
if (j == 0x0e) {
goto u3p_out;
}
continue;
u3p_cmd:
tmport = wkport + 0x10;
outb(0x30, tmport);
tmport = wkport + 0x14;
outb(0x00, tmport);
tmport += 0x04;
outb(0x08, tmport);
tmport += 0x07;
while ((inb(tmport) & 0x80) == 0x00);
tmport -= 0x08;
j = inb(tmport);
if (j != 0x16) {
if (j == 0x4e) {
goto u3p_out;
}
continue;
}
if (mbuf[0] != 0x01) {
goto chg_wide;
}
if (mbuf[1] != 0x06) {
goto chg_wide;
}
if (mbuf[2] != 0x04) {
goto chg_wide;
}
if (mbuf[3] == 0x09) {
m = 1;
m = m << i;
dev->wide_id[c] |= m;
dev->id[c][i].devsp = 0xce;
#ifdef ED_DBGP
printk("dev->id[%2d][%2d].devsp = %2x\n",c,i,dev->id[c][i].devsp);
#endif
continue;
}
chg_wide:
tmport = wkport + 0x1b;
outb(0x01, tmport);
tmport = wkport + 0x03;
outb(satn[0], tmport++);
outb(satn[1], tmport++);
outb(satn[2], tmport++);
outb(satn[3], tmport++);
outb(satn[4], tmport++);
outb(satn[5], tmport++);
tmport += 0x06;
outb(0, tmport);
tmport += 0x02;
outb(dev->id[c][i].devsp, tmport++);
outb(0, tmport++);
outb(satn[6], tmport++);
outb(satn[7], tmport++);
tmport += 0x03;
outb(satn[8], tmport);
tmport += 0x07;
while ((inb(tmport) & 0x80) == 0x00);
tmport -= 0x08;
if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
continue;
}
while (inb(tmport) != 0x8e);
try_wide:
j = 0;
tmport = wkport + 0x14;
outb(0x05, tmport);
tmport += 0x04;
outb(0x20, tmport);
tmport += 0x07;
while ((inb(tmport) & 0x80) == 0) {
if ((inb(tmport) & 0x01) != 0) {
tmport -= 0x06;
outb(wide[j++], tmport);
tmport += 0x06;
}
}
tmport -= 0x08;
while ((inb(tmport) & 0x80) == 0x00);
j = inb(tmport) & 0x0f;
if (j == 0x0f) {
goto widep_in;
}
if (j == 0x0a) {
goto widep_cmd;
}
if (j == 0x0e) {
goto try_wide;
}
continue;
widep_out:
tmport = wkport + 0x18;
outb(0x20, tmport);
tmport += 0x07;
while ((inb(tmport) & 0x80) == 0) {
if ((inb(tmport) & 0x01) != 0) {
tmport -= 0x06;
outb(0, tmport);
tmport += 0x06;
}
}
tmport -= 0x08;
j = inb(tmport) & 0x0f;
if (j == 0x0f) {
goto widep_in;
}
if (j == 0x0a) {
goto widep_cmd;
}
if (j == 0x0e) {
goto widep_out;
}
continue;
widep_in:
tmport = wkport + 0x14;
outb(0xff, tmport);
tmport += 0x04;
outb(0x20, tmport);
tmport += 0x07;
k = 0;
widep_in1:
j = inb(tmport);
if ((j & 0x01) != 0) {
tmport -= 0x06;
mbuf[k++] = inb(tmport);
tmport += 0x06;
goto widep_in1;
}
if ((j & 0x80) == 0x00) {
goto widep_in1;
}
tmport -= 0x08;
j = inb(tmport) & 0x0f;
if (j == 0x0f) {
goto widep_in;
}
if (j == 0x0a) {
goto widep_cmd;
}
if (j == 0x0e) {
goto widep_out;
}
continue;
widep_cmd:
tmport = wkport + 0x10;
outb(0x30, tmport);
tmport = wkport + 0x14;
outb(0x00, tmport);
tmport += 0x04;
outb(0x08, tmport);
tmport += 0x07;
while ((inb(tmport) & 0x80) == 0x00);
tmport -= 0x08;
j = inb(tmport);
if (j != 0x16) {
if (j == 0x4e) {
goto widep_out;
}
continue;
}
if (mbuf[0] != 0x01) {
goto not_wide;
}
if (mbuf[1] != 0x02) {
goto not_wide;
}
if (mbuf[2] != 0x03) {
goto not_wide;
}
if (mbuf[3] != 0x01) {
goto not_wide;
}
m = 1;
m = m << i;
dev->wide_id[c] |= m;
not_wide:
if ((dev->id[c][i].devtype == 0x00) || (dev->id[c][i].devtype == 0x07) ||
((dev->id[c][i].devtype == 0x05) && ((n & 0x10) != 0))) {
m = 1;
m = m << i;
if ((dev->async[c] & m) != 0) {
goto set_sync;
}
}
continue;
set_sync:
if (dev->sp[c][i] == 0x02) {
synu[4]=0x0c;
synuw[4]=0x0c;
} else {
if (dev->sp[c][i] >= 0x03) {
synu[4]=0x0a;
synuw[4]=0x0a;
}
}
tmport = wkport + 0x1b;
j = 0;
if ((m & dev->wide_id[c]) != 0) {
j |= 0x01;
}
outb(j, tmport);
tmport = wkport + 0x03;
outb(satn[0], tmport++);
outb(satn[1], tmport++);
outb(satn[2], tmport++);
outb(satn[3], tmport++);
outb(satn[4], tmport++);
outb(satn[5], tmport++);
tmport += 0x06;
outb(0, tmport);
tmport += 0x02;
outb(dev->id[c][i].devsp, tmport++);
outb(0, tmport++);
outb(satn[6], tmport++);
outb(satn[7], tmport++);
tmport += 0x03;
outb(satn[8], tmport);
tmport += 0x07;
while ((inb(tmport) & 0x80) == 0x00);
tmport -= 0x08;
if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
continue;
}
while (inb(tmport) != 0x8e);
try_sync:
j = 0;
tmport = wkport + 0x14;
outb(0x06, tmport);
tmport += 0x04;
outb(0x20, tmport);
tmport += 0x07;
while ((inb(tmport) & 0x80) == 0) {
if ((inb(tmport) & 0x01) != 0) {
tmport -= 0x06;
if ((m & dev->wide_id[c]) != 0) {
if ((m & dev->ultra_map[c]) != 0) {
outb(synuw[j++], tmport);
} else {
outb(synw[j++], tmport);
}
} else {
if ((m & dev->ultra_map[c]) != 0) {
outb(synu[j++], tmport);
} else {
outb(synn[j++], tmport);
}
}
tmport += 0x06;
}
}
tmport -= 0x08;
while ((inb(tmport) & 0x80) == 0x00);
j = inb(tmport) & 0x0f;
if (j == 0x0f) {
goto phase_ins;
}
if (j == 0x0a) {
goto phase_cmds;
}
if (j == 0x0e) {
goto try_sync;
}
continue;
phase_outs:
tmport = wkport + 0x18;
outb(0x20, tmport);
tmport += 0x07;
while ((inb(tmport) & 0x80) == 0x00) {
if ((inb(tmport) & 0x01) != 0x00) {
tmport -= 0x06;
outb(0x00, tmport);
tmport += 0x06;
}
}
tmport -= 0x08;
j = inb(tmport);
if (j == 0x85) {
goto tar_dcons;
}
j &= 0x0f;
if (j == 0x0f) {
goto phase_ins;
}
if (j == 0x0a) {
goto phase_cmds;
}
if (j == 0x0e) {
goto phase_outs;
}
continue;
phase_ins:
tmport = wkport + 0x14;
outb(0x06, tmport);
tmport += 0x04;
outb(0x20, tmport);
tmport += 0x07;
k = 0;
phase_ins1:
j = inb(tmport);
if ((j & 0x01) != 0x00) {
tmport -= 0x06;
mbuf[k++] = inb(tmport);
tmport += 0x06;
goto phase_ins1;
}
if ((j & 0x80) == 0x00) {
goto phase_ins1;
}
tmport -= 0x08;
while ((inb(tmport) & 0x80) == 0x00);
j = inb(tmport);
if (j == 0x85) {
goto tar_dcons;
}
j &= 0x0f;
if (j == 0x0f) {
goto phase_ins;
}
if (j == 0x0a) {
goto phase_cmds;
}
if (j == 0x0e) {
goto phase_outs;
}
continue;
phase_cmds:
tmport = wkport + 0x10;
outb(0x30, tmport);
tar_dcons:
tmport = wkport + 0x14;
outb(0x00, tmport);
tmport += 0x04;
outb(0x08, tmport);
tmport += 0x07;
while ((inb(tmport) & 0x80) == 0x00);
tmport -= 0x08;
j = inb(tmport);
if (j != 0x16) {
continue;
}
if (mbuf[0] != 0x01) {
continue;
}
if (mbuf[1] != 0x03) {
continue;
}
if (mbuf[4] == 0x00) {
continue;
}
if (mbuf[3] > 0x64) {
continue;
}
if (mbuf[4] > 0x0e) {
mbuf[4] = 0x0e;
}
dev->id[c][i].devsp = mbuf[4];
if (mbuf[3] < 0x0c){
j = 0xb0;
goto set_syn_ok;
}
if ((mbuf[3] < 0x0d) && (rmb == 0)) {
j = 0xa0;
goto set_syn_ok;
}
if (mbuf[3] < 0x1a) {
j = 0x20;
goto set_syn_ok;
}
if (mbuf[3] < 0x33) {
j = 0x40;
goto set_syn_ok;
}
if (mbuf[3] < 0x4c) {
j = 0x50;
goto set_syn_ok;
}
j = 0x60;
set_syn_ok:
dev->id[c][i].devsp = (dev->id[c][i].devsp & 0x0f) | j;
#ifdef ED_DBGP
printk("dev->id[%2d][%2d].devsp = %2x\n",c,i,dev->id[c][i].devsp);
#endif
}
tmport = wkport + 0x16;
outb(0x80, tmport);
}
module_init(atp870u_init); module_init(atp870u_init);
module_exit(atp870u_exit); module_exit(atp870u_exit);
...@@ -2,50 +2,64 @@ ...@@ -2,50 +2,64 @@
#define _ATP870U_H #define _ATP870U_H
#include <linux/types.h> #include <linux/types.h>
#include <linux/kdev_t.h>
/* I/O Port */ /* I/O Port */
#define MAX_CDB 12 #define MAX_CDB 12
#define MAX_SENSE 14 #define MAX_SENSE 14
#define qcnt 32 #define qcnt 32
#define ATP870U_SCATTER 128 #define ATP870U_SCATTER 128
#define ATP870U_CMDLUN 1 #define ATP870U_CMDLUN 1
struct atp_unit { #define MAX_ADAPTER 8
unsigned long ioport; #define MAX_SCSI_ID 16
unsigned long pciport; #define ATP870U_MAX_SECTORS 128
unsigned char last_cmd;
unsigned char in_snd; #define ATP885_DEVID 0x808A
unsigned char in_int; #define ATP880_DEVID1 0x8080
unsigned char quhdu; #define ATP880_DEVID2 0x8081
unsigned char quendu;
//#define ED_DBGP
struct atp_unit
{
unsigned long baseport;
unsigned long ioport[2];
unsigned long pciport[2];
unsigned long irq;
unsigned char last_cmd[2];
unsigned char in_snd[2];
unsigned char in_int[2];
unsigned char quhd[2];
unsigned char quend[2];
unsigned char global_map[2];
unsigned char chip_ver;
unsigned char scam_on; unsigned char scam_on;
unsigned char global_map; unsigned char host_id[2];
unsigned char chip_veru; unsigned int working[2];
unsigned char host_idu; unsigned short wide_id[2];
volatile int working; unsigned short active_id[2];
unsigned short wide_idu; unsigned short ultra_map[2];
unsigned short active_idu; unsigned short async[2];
unsigned short ultra_map; unsigned short dev_id;
unsigned short async; unsigned char sp[2][16];
unsigned short deviceid; unsigned char r1f[2][16];
unsigned char ata_cdbu[16]; struct scsi_cmnd *quereq[2][qcnt];
unsigned char sp[16]; struct atp_id
struct scsi_cmnd *querequ[qcnt]; {
struct atp_id { unsigned char dirct;
unsigned char dirctu; unsigned char devsp;
unsigned char devspu; unsigned char devtype;
unsigned char devtypeu; unsigned long tran_len;
unsigned long prdaddru; unsigned long last_len;
unsigned long tran_lenu; unsigned char *prd_pos;
unsigned long last_lenu; unsigned char *prd_table;
unsigned char *prd_posu; dma_addr_t prdaddr;
unsigned char *prd_tableu;
dma_addr_t prd_phys;
struct scsi_cmnd *curr_req; struct scsi_cmnd *curr_req;
} id[16]; } id[2][16];
struct Scsi_Host *host; struct Scsi_Host *host;
struct pci_dev *pdev; struct pci_dev *pdev;
unsigned int unit; unsigned int unit;
}; };
......
...@@ -1497,6 +1497,9 @@ ...@@ -1497,6 +1497,9 @@
#define PCI_DEVICE_ID_ARTOP_AEC7612D 0x8040 #define PCI_DEVICE_ID_ARTOP_AEC7612D 0x8040
#define PCI_DEVICE_ID_ARTOP_AEC7612SUW 0x8050 #define PCI_DEVICE_ID_ARTOP_AEC7612SUW 0x8050
#define PCI_DEVICE_ID_ARTOP_8060 0x8060 #define PCI_DEVICE_ID_ARTOP_8060 0x8060
#define PCI_DEVICE_ID_ARTOP_AEC67160 0x8080
#define PCI_DEVICE_ID_ARTOP_AEC67160_2 0x8081
#define PCI_DEVICE_ID_ARTOP_AEC67162 0x808a
#define PCI_VENDOR_ID_ZEITNET 0x1193 #define PCI_VENDOR_ID_ZEITNET 0x1193
#define PCI_DEVICE_ID_ZEITNET_1221 0x0001 #define PCI_DEVICE_ID_ZEITNET_1221 0x0001
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment