Commit 92a9a651 authored by Guennadi Liakhovetski's avatar Guennadi Liakhovetski Committed by James Bottomley

[PATCH] refactor tmscsim inititalization code

Streamline EEPROM handling code

The patch below is a fixed (and slightly reworked) patch from Christoph.
Thanks to Chiaki Ishikawa for fixes and tests.

Original author: Christoph Hellwig
Signed-off-by: default avatarGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent d7768998
...@@ -2297,28 +2297,72 @@ static struct scsi_host_template driver_template = { ...@@ -2297,28 +2297,72 @@ static struct scsi_host_template driver_template = {
* *
**********************************************************************/ **********************************************************************/
static void __devinit dc390_eeprom_prepare_read(struct pci_dev *pdev, u8 cmd)
{
u8 carryFlag = 1, j = 0x80, bval;
int i;
for (i = 0; i < 9; i++) {
if (carryFlag) {
pci_write_config_byte(pdev, 0x80, 0x40);
bval = 0xc0;
} else
bval = 0x80;
udelay(160);
pci_write_config_byte(pdev, 0x80, bval);
udelay(160);
pci_write_config_byte(pdev, 0x80, 0);
udelay(160);
static void __devinit dc390_EnDisableCE(u8 mode, struct pci_dev *pdev, u8 *regval) carryFlag = (cmd & j) ? 1 : 0;
j >>= 1;
}
}
static u16 __devinit dc390_eeprom_get_data(struct pci_dev *pdev)
{ {
int i;
u16 wval = 0;
u8 bval; u8 bval;
bval = 0; for (i = 0; i < 16; i++) {
if(mode == ENABLE_CE) wval <<= 1;
*regval = 0xc0;
else pci_write_config_byte(pdev, 0x80, 0x80);
*regval = 0x80;
pci_write_config_byte(pdev, *regval, bval);
if(mode == DISABLE_CE)
pci_write_config_byte(pdev, *regval, bval);
udelay(160); udelay(160);
pci_write_config_byte(pdev, 0x80, 0x40);
udelay(160);
pci_read_config_byte(pdev, 0x00, &bval);
if (bval == 0x22)
wval |= 1;
}
return wval;
} }
static void __devinit dc390_read_eeprom(struct pci_dev *pdev, u16 *ptr)
{
u8 cmd = EEPROM_READ, i;
for (i = 0; i < 0x40; i++) {
pci_write_config_byte(pdev, 0xc0, 0);
udelay(160);
dc390_eeprom_prepare_read(pdev, cmd++);
*ptr++ = dc390_eeprom_get_data(pdev);
pci_write_config_byte(pdev, 0x80, 0);
pci_write_config_byte(pdev, 0x80, 0);
udelay(160);
}
}
/* Override EEprom values with explicitly set values */ /* Override EEprom values with explicitly set values */
static void __devinit dc390_EEprom_Override (u8 index) static void __devinit dc390_eeprom_override(u8 index)
{ {
u8 *ptr = (u8 *) dc390_eepromBuf[index]; u8 *ptr = (u8 *) dc390_eepromBuf[index], id;
u8 id;
/* Adapter Settings */ /* Adapter Settings */
if (tmscsim[0] != -2) if (tmscsim[0] != -2)
...@@ -2331,166 +2375,81 @@ static void __devinit dc390_EEprom_Override (u8 index) ...@@ -2331,166 +2375,81 @@ static void __devinit dc390_EEprom_Override (u8 index)
ptr[EE_TAG_CMD_NUM] = (u8)tmscsim[4]; /* Tagged Cmds */ ptr[EE_TAG_CMD_NUM] = (u8)tmscsim[4]; /* Tagged Cmds */
/* Device Settings */ /* Device Settings */
for (id = 0; id < MAX_SCSI_ID; id++) for (id = 0; id < MAX_SCSI_ID; id++) {
{
if (tmscsim[2] != -2) if (tmscsim[2] != -2)
ptr[id<<2] = (u8)tmscsim[2]; /* EE_MODE1 */ ptr[id << 2] = (u8)tmscsim[2]; /* EE_MODE1 */
if (tmscsim[1] != -2) if (tmscsim[1] != -2)
ptr[(id<<2) + 1] = (u8)tmscsim[1]; /* EE_Speed */ ptr[(id << 2) + 1] = (u8)tmscsim[1]; /* EE_Speed */
}
}
/* Handle "-1" case */
static void __devinit dc390_check_for_safe_settings (void)
{
if (tmscsim[0] == -1 || tmscsim[0] > 15) /* modules-2.0.0 passes -1 as string */
{
tmscsim[0] = 7; tmscsim[1] = 4;
tmscsim[2] = 0x09; tmscsim[3] = 0x0f;
tmscsim[4] = 2; tmscsim[5] = 10;
printk (KERN_INFO "DC390: Using safe settings.\n");
} }
} }
static int __devinitdata tmscsim_def[] = {
static int __initdata tmscsim_def[] = {7, 0 /* 10MHz */, 7,
PARITY_CHK_ | SEND_START_ | EN_DISCONNECT_ 0 /* 10MHz */,
| SYNC_NEGO_ | TAG_QUEUEING_, PARITY_CHK_ | SEND_START_ | EN_DISCONNECT_ | SYNC_NEGO_ | TAG_QUEUEING_,
MORE2_DRV | GREATER_1G | RST_SCSI_BUS | ACTIVE_NEGATION MORE2_DRV | GREATER_1G | RST_SCSI_BUS | ACTIVE_NEGATION | LUN_CHECK,
/* | NO_SEEK */ 3 /* 16 Tags per LUN */,
# ifdef CONFIG_SCSI_MULTI_LUN 1 /* s delay after Reset */,
| LUN_CHECK };
# endif
, 3 /* 16 Tags per LUN */, 1 /* s delay after Reset */ };
/* Copy defaults over set values where missing */ /* Copy defaults over set values where missing */
static void __devinit dc390_fill_with_defaults (void) static void __devinit dc390_fill_with_defaults (void)
{ {
int i; int i;
PARSEDEBUG(printk(KERN_INFO "DC390: setup %08x %08x %08x %08x %08x %08x\n", tmscsim[0],\
tmscsim[1], tmscsim[2], tmscsim[3], tmscsim[4], tmscsim[5])); for (i = 0; i < 6; i++) {
for (i = 0; i < 6; i++)
{
if (tmscsim[i] < 0 || tmscsim[i] > 255) if (tmscsim[i] < 0 || tmscsim[i] > 255)
tmscsim[i] = tmscsim_def[i]; tmscsim[i] = tmscsim_def[i];
} }
/* Sanity checks */
if (tmscsim[0] > 7) tmscsim[0] = 7;
if (tmscsim[1] > 7) tmscsim[1] = 4;
if (tmscsim[4] > 5) tmscsim[4] = 4;
if (tmscsim[5] > 180) tmscsim[5] = 180;
}
static void __devinit dc390_EEpromOutDI(struct pci_dev *pdev, u8 *regval, u8 Carry)
{
u8 bval;
bval = 0;
if(Carry)
{
bval = 0x40;
*regval = 0x80;
pci_write_config_byte(pdev, *regval, bval);
}
udelay(160);
bval |= 0x80;
pci_write_config_byte(pdev, *regval, bval);
udelay(160);
bval = 0;
pci_write_config_byte(pdev, *regval, bval);
udelay(160);
}
static u8 __devinit dc390_EEpromInDO(struct pci_dev *pdev) /* Sanity checks */
{ if (tmscsim[0] > 7)
u8 bval; tmscsim[0] = 7;
if (tmscsim[1] > 7)
pci_write_config_byte(pdev, 0x80, 0x80); tmscsim[1] = 4;
udelay(160); if (tmscsim[4] > 5)
pci_write_config_byte(pdev, 0x80, 0x40); tmscsim[4] = 4;
udelay(160); if (tmscsim[5] > 180)
pci_read_config_byte(pdev, 0x00, &bval); tmscsim[5] = 180;
if(bval == 0x22)
return(1);
else
return(0);
} }
static void __devinit dc390_check_eeprom(struct pci_dev *pdev, u8 index)
static u16 __devinit dc390_EEpromGetData1(struct pci_dev *pdev)
{ {
u8 i; u8 interpd[] = {1, 3, 5, 10, 16, 30, 60, 120};
u8 carryFlag; u8 EEbuf[128];
u16 wval; u16 *ptr = (u16 *)EEbuf, wval = 0;
int i;
wval = 0; dc390_read_eeprom(pdev, ptr);
for(i=0; i<16; i++) memcpy(dc390_eepromBuf[index], EEbuf, EE_ADAPT_SCSI_ID);
{ memcpy(&dc390_eepromBuf[index][EE_ADAPT_SCSI_ID],
wval <<= 1; &EEbuf[REAL_EE_ADAPT_SCSI_ID], EE_LEN - EE_ADAPT_SCSI_ID);
carryFlag = dc390_EEpromInDO(pdev);
wval |= carryFlag;
}
return(wval);
}
dc390_eepromBuf[index][EE_DELAY] = interpd[dc390_eepromBuf[index][EE_DELAY]];
static void __devinit dc390_Prepare(struct pci_dev *pdev, u8 *regval, u8 EEpromCmd) for (i = 0; i < 0x40; i++, ptr++)
{ wval += *ptr;
u8 i,j;
u8 carryFlag;
carryFlag = 1; /* no Tekram EEprom found */
j = 0x80; if (wval != 0x1234) {
for(i=0; i<9; i++) int speed;
{
dc390_EEpromOutDI(pdev, regval, carryFlag);
carryFlag = (EEpromCmd & j) ? 1 : 0;
j >>= 1;
}
}
printk(KERN_INFO "DC390_init: No EEPROM found! Trying default settings ...\n");
static void __devinit dc390_ReadEEprom(struct pci_dev *pdev, u16 *ptr) /*
{ * XXX(hch): bogus, because we might have tekram and
u8 regval,cmd; * non-tekram hbas in a single machine.
u8 i; */
dc390_fill_with_defaults();
cmd = EEPROM_READ; speed = dc390_clock_speed[tmscsim[1]];
for(i=0; i<0x40; i++) printk(KERN_INFO "DC390: Used defaults: AdaptID=%i, SpeedIdx=%i (%i.%i MHz), "
{ "DevMode=0x%02x, AdaptMode=0x%02x, TaggedCmnds=%i (%i), DelayReset=%is\n",
dc390_EnDisableCE(ENABLE_CE, pdev, &regval); tmscsim[0], tmscsim[1], speed / 10, speed % 10,
dc390_Prepare(pdev, &regval, cmd++); (u8)tmscsim[2], (u8)tmscsim[3], tmscsim[4], 2 << (tmscsim[4]), tmscsim[5]);
*ptr++ = dc390_EEpromGetData1(pdev);
dc390_EnDisableCE(DISABLE_CE, pdev, &regval);
} }
} }
static void __devinit dc390_interpret_delay (u8 index)
{
char interpd [] = {1,3,5,10,16,30,60,120};
dc390_eepromBuf[index][EE_DELAY] = interpd [dc390_eepromBuf[index][EE_DELAY]];
}
static u8 __devinit dc390_CheckEEpromCheckSum(struct pci_dev *pdev, u8 index)
{
u8 i;
char EEbuf[128];
u16 wval, *ptr = (u16 *)EEbuf;
dc390_ReadEEprom(pdev, ptr);
memcpy (dc390_eepromBuf[index], EEbuf, EE_ADAPT_SCSI_ID);
memcpy (&dc390_eepromBuf[index][EE_ADAPT_SCSI_ID],
&EEbuf[REAL_EE_ADAPT_SCSI_ID], EE_LEN - EE_ADAPT_SCSI_ID);
dc390_interpret_delay (index);
wval = 0;
for(i=0; i<0x40; i++, ptr++)
wval += *ptr;
return (wval == 0x1234 ? 0 : 1);
}
static void __devinit dc390_init_hw(struct dc390_acb *pACB, u8 index) static void __devinit dc390_init_hw(struct dc390_acb *pACB, u8 index)
{ {
struct Scsi_Host *shost = pACB->pScsiHost; struct Scsi_Host *shost = pACB->pScsiHost;
...@@ -2562,21 +2521,8 @@ static int __devinit dc390_probe_one(struct pci_dev *pdev, ...@@ -2562,21 +2521,8 @@ static int __devinit dc390_probe_one(struct pci_dev *pdev,
pACB = (struct dc390_acb *)shost->hostdata; pACB = (struct dc390_acb *)shost->hostdata;
memset(pACB, 0, sizeof(struct dc390_acb)); memset(pACB, 0, sizeof(struct dc390_acb));
if (dc390_CheckEEpromCheckSum(pdev, dc390_adapterCnt)) { dc390_check_eeprom(pdev, dc390_adapterCnt);
int speed; dc390_eeprom_override(dc390_adapterCnt);
printk(KERN_INFO "DC390_init: No EEPROM found! Trying default settings ...\n");
dc390_check_for_safe_settings();
dc390_fill_with_defaults();
dc390_EEprom_Override(dc390_adapterCnt);
speed = dc390_clock_speed[tmscsim[1]];
printk(KERN_INFO "DC390: Used defaults: AdaptID=%i, SpeedIdx=%i (%i.%i MHz),"
" DevMode=0x%02x, AdaptMode=0x%02x, TaggedCmnds=%i (%i), DelayReset=%is\n",
tmscsim[0], tmscsim[1], speed/10, speed%10,
(u8)tmscsim[2], (u8)tmscsim[3], tmscsim[4], 2 << (tmscsim[4]), tmscsim[5]);
} else {
dc390_check_for_safe_settings();
dc390_EEprom_Override(dc390_adapterCnt);
}
io_port = pci_resource_start(pdev, 0); io_port = pci_resource_start(pdev, 0);
...@@ -2703,6 +2649,16 @@ static struct pci_driver dc390_driver = { ...@@ -2703,6 +2649,16 @@ static struct pci_driver dc390_driver = {
static int __init dc390_module_init(void) static int __init dc390_module_init(void)
{ {
if (tmscsim[0] == -1 || tmscsim[0] > 15) {
tmscsim[0] = 7;
tmscsim[1] = 4;
tmscsim[2] = PARITY_CHK_ | TAG_QUEUEING_;
tmscsim[3] = MORE2_DRV | GREATER_1G | RST_SCSI_BUS | ACTIVE_NEGATION;
tmscsim[4] = 2;
tmscsim[5] = 10;
printk (KERN_INFO "DC390: Using safe settings.\n");
}
return pci_module_init(&dc390_driver); return pci_module_init(&dc390_driver);
} }
......
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