Hi
Here's an attempt of a SCSI transport API implementation for tmscsim.
Please, comment.
Test booted with 3 sync devices on the bus, tried to changed period from
100ns to 150ns (148 was set), read throughput fell from 7900000 to 5900000
bytes/sec (measured with dd). Is it about the expected drop?
Not sure if I chose a good place for spi_display_xfer_agreement() - it now
happens 8 times (!) per target...
Thanks
Guennadi
---
Guennadi Liakhovetski
Signed-off-by: Guennadi Liakhovetski <[EMAIL PROTECTED]>
Index: linux-2.6.13/drivers/scsi/tmscsim.c
===================================================================
RCS file: /usr/src/cvs/linux-2_6/drivers/scsi/tmscsim.c,v
retrieving revision 1.1.1.9
diff -u -p -r1.1.1.9 tmscsim.c
--- linux-2.6.13/drivers/scsi/tmscsim.c 2 Sep 2005 19:16:29 -0000 1.1.1.9
+++ linux-2.6.13/drivers/scsi/tmscsim.c 9 Sep 2005 20:04:25 -0000
@@ -243,7 +243,7 @@
#include <scsi/scsi_host.h>
#include <scsi/scsicam.h>
#include <scsi/scsi_tcq.h>
-
+#include <scsi/scsi_transport_spi.h>
#define DC390_BANNER "Tekram DC390/AM53C974"
#define DC390_VERSION "2.1d 2004-05-27"
@@ -277,6 +277,8 @@ static void dc390_EnableMsgOut_Abort(str
static void dc390_dumpinfo(struct dc390_acb* pACB, struct dc390_dcb* pDCB,
struct dc390_srb* pSRB);
static void dc390_ResetDevParam(struct dc390_acb* pACB);
+static struct scsi_transport_template *dc390_transport_template;
+
static u32 dc390_laststatus = 0;
static u8 dc390_adapterCnt = 0;
@@ -519,7 +521,7 @@ dc390_StartSCSI( struct dc390_acb* pACB,
/* TODO: error handling */
DC390_write8 (Scsi_Dest_ID, pDCB->TargetID);
DC390_write8 (Sync_Period, pDCB->SyncPeriod);
- DC390_write8 (Sync_Offset, pDCB->SyncOffset);
+ DC390_write8 (Sync_Offset, spi_offset(pDCB->starget));
DC390_write8 (CtrlReg1, pDCB->CtrlR1);
DC390_write8 (CtrlReg3, pDCB->CtrlR3);
DC390_write8 (CtrlReg4, pDCB->CtrlR4);
@@ -565,7 +567,7 @@ dc390_StartSCSI( struct dc390_acb* pACB,
if (try_sync_nego)
{
- u8 Sync_Off = pDCB->SyncOffset;
+ u8 Sync_Off = spi_offset(pDCB->starget);
DEBUG0(printk (KERN_INFO "DC390: NEW Sync Nego code triggered (%i
%i)\n", pDCB->TargetID, pDCB->TargetLUN));
pSRB->MsgOutBuf[0] = EXTENDED_MESSAGE;
pSRB->MsgOutBuf[1] = 3;
@@ -1038,10 +1040,11 @@ static void __inline__
dc390_reprog (struct dc390_acb* pACB, struct dc390_dcb* pDCB)
{
DC390_write8 (Sync_Period, pDCB->SyncPeriod);
- DC390_write8 (Sync_Offset, pDCB->SyncOffset);
+ DC390_write8 (Sync_Offset, spi_offset(pDCB->starget));
DC390_write8 (CtrlReg3, pDCB->CtrlR3);
DC390_write8 (CtrlReg4, pDCB->CtrlR4);
dc390_SetXferRate (pACB, pDCB);
+ spi_display_xfer_agreement(pDCB->starget);
}
@@ -1123,7 +1126,8 @@ dc390_MsgIn_set_async (struct dc390_acb*
pSRB->SRBState &= ~DO_SYNC_NEGO;
pDCB->SyncMode &= ~(SYNC_ENABLE+SYNC_NEGO_DONE);
pDCB->SyncPeriod = 0;
- pDCB->SyncOffset = 0;
+ spi_period(pDCB->starget) = 0;
+ spi_offset(pDCB->starget) = 0;
//pDCB->NegoPeriod = 50; /* 200ns <=> 5 MHz */
pDCB->CtrlR3 = FAST_CLK; /* fast clock / normal scsi */
pDCB->CtrlR4 &= 0x3f;
@@ -1139,7 +1143,7 @@ dc390_MsgIn_set_sync (struct dc390_acb*
u16 wval, wval1;
struct dc390_dcb* pDCB = pSRB->pSRBDCB;
u8 oldsyncperiod = pDCB->SyncPeriod;
- u8 oldsyncoffset = pDCB->SyncOffset;
+ u8 oldsyncoffset = spi_offset(pDCB->starget);
if (!(pSRB->SRBState & DO_SYNC_NEGO))
{
@@ -1168,8 +1172,8 @@ dc390_MsgIn_set_sync (struct dc390_acb*
pSRB->SRBState &= ~DO_SYNC_NEGO;
pDCB->SyncMode |= SYNC_ENABLE+SYNC_NEGO_DONE;
- pDCB->SyncOffset &= 0x0f0;
- pDCB->SyncOffset |= pSRB->MsgInBuf[4];
+ spi_offset(pDCB->starget) &= 0xf0;
+ spi_offset(pDCB->starget) |= pSRB->MsgInBuf[4];
pDCB->NegoPeriod = pSRB->MsgInBuf[3];
wval = (u16) pSRB->MsgInBuf[3];
@@ -1193,14 +1197,15 @@ dc390_MsgIn_set_sync (struct dc390_acb*
pDCB->CtrlR3 = bval;
pDCB->SyncPeriod = (u8)wval1;
-
- if ((oldsyncperiod != wval1 || oldsyncoffset != pDCB->SyncOffset) &&
pDCB->TargetLUN == 0)
+ spi_period(pDCB->starget) = pSRB->MsgInBuf[3];
+ if ((oldsyncperiod != wval1 || oldsyncoffset != spi_offset(pDCB->starget)) &&
+ pDCB->TargetLUN == 0)
{
if (! (bval & FAST_SCSI)) wval1++;
printk (KERN_INFO "DC390: Target %i: Sync transfer %i.%1i MHz, Offset
%i\n", pDCB->TargetID,
- 40/wval1, ((40%wval1)*10+wval1/2)/wval1, pDCB->SyncOffset & 0x0f);
+ 40/wval1, ((40%wval1)*10+wval1/2)/wval1,
spi_offset(pDCB->starget) & 0x0f);
}
-
+
dc390_reprog (pACB, pDCB);
}
@@ -1529,8 +1534,8 @@ mop1:
DC390_write8 (ScsiFifo, 3); /* ;length of extended msg */
DC390_write8 (ScsiFifo, EXTENDED_SDTR); /* ; sync nego */
DC390_write8 (ScsiFifo, pDCB->NegoPeriod);
- if (pDCB->SyncOffset & 0x0f)
- DC390_write8 (ScsiFifo, pDCB->SyncOffset);
+ if (spi_offset(pDCB->starget) & 0x0f)
+ DC390_write8 (ScsiFifo, spi_offset(pDCB->starget));
else
DC390_write8 (ScsiFifo, SYNC_NEGO_OFFSET);
pSRB->SRBState |= DO_SYNC_NEGO;
@@ -1580,7 +1585,8 @@ dc390_SetXferRate( struct dc390_acb* pAC
if( ptr->TargetID == bval )
{
ptr->SyncPeriod = pDCB->SyncPeriod;
- ptr->SyncOffset = pDCB->SyncOffset;
+ spi_period(ptr->starget) = spi_period(pDCB->starget);
+ spi_offset(ptr->starget) = spi_offset(pDCB->starget);
ptr->CtrlR3 = pDCB->CtrlR3;
ptr->CtrlR4 = pDCB->CtrlR4;
ptr->SyncMode = pDCB->SyncMode;
@@ -1738,7 +1744,7 @@ dc390_Reselect( struct dc390_acb* pACB )
pSRB->ScsiPhase = SCSI_NOP0;
DC390_write8 (Scsi_Dest_ID, pDCB->TargetID);
DC390_write8 (Sync_Period, pDCB->SyncPeriod);
- DC390_write8 (Sync_Offset, pDCB->SyncOffset);
+ DC390_write8 (Sync_Offset, spi_offset(pDCB->starget));
DC390_write8 (CtrlReg1, pDCB->CtrlR1);
DC390_write8 (CtrlReg3, pDCB->CtrlR3);
DC390_write8 (CtrlReg4, pDCB->CtrlR4); /* ; Glitch eater */
@@ -2103,7 +2109,8 @@ static void dc390_ResetDevParam( struct
{
pDCB->SyncMode &= ~SYNC_NEGO_DONE;
pDCB->SyncPeriod = 0;
- pDCB->SyncOffset = 0;
+ spi_period(pDCB->starget) = 0;
+ spi_offset(pDCB->starget) = 0;
pDCB->TagMask = 0;
pDCB->CtrlR3 = FAST_CLK;
pDCB->CtrlR4 &= NEGATE_REQACKDATA | CTRL4_RESERVED | NEGATE_REQACK;
@@ -2180,6 +2187,10 @@ static int dc390_slave_alloc(struct scsi
pDCB->pDCBACB = pACB;
pDCB->TargetID = id;
pDCB->TargetLUN = lun;
+ pDCB->starget = scsi_device->sdev_target;
+
+ spi_width(pDCB->starget) = 0;
+ spi_max_width(pDCB->starget) = 0;
/*
* Some values are for all LUNs: Copy them
@@ -2189,9 +2200,10 @@ static int dc390_slave_alloc(struct scsi
pDCB->DevMode = pDCB2->DevMode;
pDCB->SyncMode = pDCB2->SyncMode & SYNC_NEGO_DONE;
pDCB->SyncPeriod = pDCB2->SyncPeriod;
- pDCB->SyncOffset = pDCB2->SyncOffset;
+ spi_period(pDCB->starget) = spi_period(pDCB2->starget);
+ spi_offset(pDCB->starget) = spi_offset(pDCB2->starget);
pDCB->NegoPeriod = pDCB2->NegoPeriod;
-
+
pDCB->CtrlR3 = pDCB2->CtrlR3;
pDCB->CtrlR4 = pDCB2->CtrlR4;
} else {
@@ -2211,7 +2223,7 @@ static int dc390_slave_alloc(struct scsi
pDCB->SyncMode |= SYNC_ENABLE;
else {
pDCB->SyncMode = 0;
- pDCB->SyncOffset &= ~0x0f;
+ spi_offset(pDCB->starget) &= ~0x0f;
}
pDCB->CtrlR1 = pACB->pScsiHost->this_id;
@@ -2275,6 +2287,9 @@ static int dc390_slave_configure(struct
scsi_activate_tcq(sdev, acb->TagMaxNum);
}
+ if (!spi_initial_dv(sdev->sdev_target))
+ spi_dv_device(sdev);
+
return 0;
}
@@ -2537,7 +2552,8 @@ static int __devinit dc390_probe_one(str
shost->base = io_port;
shost->unique_id = io_port;
shost->last_reset = jiffies;
-
+ shost->transportt = dc390_transport_template;
+
pACB->pScsiHost = shost;
pACB->IOPortBase = (u16) io_port;
pACB->IRQLevel = pdev->irq;
@@ -2592,6 +2608,8 @@ static int __devinit dc390_probe_one(str
error = scsi_add_host(shost, &pdev->dev);
if (error)
goto out_free_irq;
+
+ spi_signalling(shost) = SPI_SIGNAL_SE;
scsi_scan_host(shost);
return 0;
@@ -2637,6 +2655,60 @@ static void __devexit dc390_remove_one(s
pci_set_drvdata(dev, NULL);
}
+static void dc390_set_offset(struct scsi_target *starget, int offset)
+{
+ if (!spi_period(starget))
+ return;
+
+ if (offset > 15)
+ offset = 15;
+ else if (offset < 0)
+ offset = 0;
+
+ spi_offset(starget) = offset;
+}
+
+static void dc390_set_period(struct scsi_target *starget, int period)
+{
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ struct dc390_acb *pACB = (struct dc390_acb *)shost->hostdata;
+ struct dc390_dcb *pDCB = pACB->pLinkDCB;
+ u16 wval;
+
+ if (!spi_period(starget))
+ return;
+
+ if (!pDCB)
+ return;
+
+ while (pDCB->starget != starget) {
+ pDCB = pDCB->pNextDCB;
+ if (pDCB == pACB->pLinkDCB)
+ return;
+ }
+
+ if (period < pDCB->NegoPeriod)
+ period = pDCB->NegoPeriod;
+
+ /* See calculations in dc390_MsgIn_set_sync() for reference */
+ wval = (period << 2) - 3;
+ wval = ((wval + 24) / 25);
+
+ if (wval >= 8)
+ wval--;
+
+ spi_period(starget) = period;
+ pDCB->SyncPeriod = (u8)wval;
+}
+
+static struct spi_function_template dc390_transport_functions = {
+ .set_offset = dc390_set_offset,
+ .show_offset = 1,
+ .set_period = dc390_set_period,
+ .show_period = 1,
+ .show_width = 1,
+};
+
static struct pci_device_id tmscsim_pci_tbl[] = {
{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD53C974,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
@@ -2653,6 +2725,8 @@ static struct pci_driver dc390_driver =
static int __init dc390_module_init(void)
{
+ int err;
+
if (tmscsim[0] == -1 || tmscsim[0] > 15) {
tmscsim[0] = 7;
tmscsim[1] = 4;
@@ -2663,12 +2737,22 @@ static int __init dc390_module_init(void
printk (KERN_INFO "DC390: Using safe settings.\n");
}
- return pci_module_init(&dc390_driver);
+ dc390_transport_template =
spi_attach_transport(&dc390_transport_functions);
+ if (!dc390_transport_template)
+ return -ENODEV;
+
+ err = pci_register_driver(&dc390_driver);
+
+ if (err)
+ spi_release_transport(dc390_transport_template);
+
+ return err;
}
static void __exit dc390_module_exit(void)
{
pci_unregister_driver(&dc390_driver);
+ spi_release_transport(dc390_transport_template);
}
module_init(dc390_module_init);
Index: linux-2.6.13/drivers/scsi/tmscsim.h
===================================================================
RCS file: /usr/src/cvs/linux-2_6/drivers/scsi/tmscsim.h,v
retrieving revision 1.1.1.6
diff -u -p -r1.1.1.6 tmscsim.h
--- linux-2.6.13/drivers/scsi/tmscsim.h 13 Jan 2005 21:10:01 -0000 1.1.1.6
+++ linux-2.6.13/drivers/scsi/tmscsim.h 8 Sep 2005 20:51:00 -0000
@@ -82,6 +82,7 @@ struct dc390_dcb
{
struct dc390_dcb *pNextDCB;
struct dc390_acb *pDCBACB;
+struct scsi_target *starget;
/* Queued SRBs */
struct dc390_srb *pGoingSRB;
@@ -103,7 +104,6 @@ u8 CtrlR4;
u8 SyncMode; /*; 0:async mode */
u8 NegoPeriod; /*;for nego. */
u8 SyncPeriod; /*;for reg. */
-u8 SyncOffset; /*;for reg. and nego.(low nibble) */
};
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html