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,198 +2297,157 @@ static struct scsi_host_template driver_template = {
*
**********************************************************************/
static void __devinit dc390_EnDisableCE(u8 mode, struct pci_dev *pdev, u8 *regval)
static void __devinit dc390_eeprom_prepare_read(struct pci_dev *pdev, u8 cmd)
{
u8 bval;
u8 carryFlag = 1, j = 0x80, bval;
int i;
bval = 0;
if(mode == ENABLE_CE)
*regval = 0xc0;
else
*regval = 0x80;
pci_write_config_byte(pdev, *regval, bval);
if(mode == DISABLE_CE)
pci_write_config_byte(pdev, *regval, bval);
udelay(160);
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);
carryFlag = (cmd & j) ? 1 : 0;
j >>= 1;
}
}
/* Override EEprom values with explicitly set values */
static void __devinit dc390_EEprom_Override (u8 index)
static u16 __devinit dc390_eeprom_get_data(struct pci_dev *pdev)
{
u8 *ptr = (u8 *) dc390_eepromBuf[index];
u8 id;
/* Adapter Settings */
if (tmscsim[0] != -2)
ptr[EE_ADAPT_SCSI_ID] = (u8)tmscsim[0]; /* Adapter ID */
if (tmscsim[3] != -2)
ptr[EE_MODE2] = (u8)tmscsim[3];
if (tmscsim[5] != -2)
ptr[EE_DELAY] = tmscsim[5]; /* Reset delay */
if (tmscsim[4] != -2)
ptr[EE_TAG_CMD_NUM] = (u8)tmscsim[4]; /* Tagged Cmds */
/* Device Settings */
for (id = 0; id < MAX_SCSI_ID; id++)
{
if (tmscsim[2] != -2)
ptr[id<<2] = (u8)tmscsim[2]; /* EE_MODE1 */
if (tmscsim[1] != -2)
ptr[(id<<2) + 1] = (u8)tmscsim[1]; /* EE_Speed */
}
int i;
u16 wval = 0;
u8 bval;
for (i = 0; i < 16; i++) {
wval <<= 1;
pci_write_config_byte(pdev, 0x80, 0x80);
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;
}
/* Handle "-1" case */
static void __devinit dc390_check_for_safe_settings (void)
static void __devinit dc390_read_eeprom(struct pci_dev *pdev, u16 *ptr)
{
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");
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 */
static void __devinit dc390_eeprom_override(u8 index)
{
u8 *ptr = (u8 *) dc390_eepromBuf[index], id;
/* Adapter Settings */
if (tmscsim[0] != -2)
ptr[EE_ADAPT_SCSI_ID] = (u8)tmscsim[0]; /* Adapter ID */
if (tmscsim[3] != -2)
ptr[EE_MODE2] = (u8)tmscsim[3];
if (tmscsim[5] != -2)
ptr[EE_DELAY] = tmscsim[5]; /* Reset delay */
if (tmscsim[4] != -2)
ptr[EE_TAG_CMD_NUM] = (u8)tmscsim[4]; /* Tagged Cmds */
/* Device Settings */
for (id = 0; id < MAX_SCSI_ID; id++) {
if (tmscsim[2] != -2)
ptr[id << 2] = (u8)tmscsim[2]; /* EE_MODE1 */
if (tmscsim[1] != -2)
ptr[(id << 2) + 1] = (u8)tmscsim[1]; /* EE_Speed */
}
}
static int __initdata tmscsim_def[] = {7, 0 /* 10MHz */,
PARITY_CHK_ | SEND_START_ | EN_DISCONNECT_
| SYNC_NEGO_ | TAG_QUEUEING_,
MORE2_DRV | GREATER_1G | RST_SCSI_BUS | ACTIVE_NEGATION
/* | NO_SEEK */
# ifdef CONFIG_SCSI_MULTI_LUN
| LUN_CHECK
# endif
, 3 /* 16 Tags per LUN */, 1 /* s delay after Reset */ };
static int __devinitdata tmscsim_def[] = {
7,
0 /* 10MHz */,
PARITY_CHK_ | SEND_START_ | EN_DISCONNECT_ | SYNC_NEGO_ | TAG_QUEUEING_,
MORE2_DRV | GREATER_1G | RST_SCSI_BUS | ACTIVE_NEGATION | LUN_CHECK,
3 /* 16 Tags per LUN */,
1 /* s delay after Reset */,
};
/* Copy defaults over set values where missing */
static void __devinit dc390_fill_with_defaults (void)
{
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)
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)
{
u8 bval;
pci_write_config_byte(pdev, 0x80, 0x80);
udelay(160);
pci_write_config_byte(pdev, 0x80, 0x40);
udelay(160);
pci_read_config_byte(pdev, 0x00, &bval);
if(bval == 0x22)
return(1);
else
return(0);
}
static u16 __devinit dc390_EEpromGetData1(struct pci_dev *pdev)
{
u8 i;
u8 carryFlag;
u16 wval;
wval = 0;
for(i=0; i<16; i++)
{
wval <<= 1;
carryFlag = dc390_EEpromInDO(pdev);
wval |= carryFlag;
}
return(wval);
/* 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_Prepare(struct pci_dev *pdev, u8 *regval, u8 EEpromCmd)
static void __devinit dc390_check_eeprom(struct pci_dev *pdev, u8 index)
{
u8 i,j;
u8 carryFlag;
u8 interpd[] = {1, 3, 5, 10, 16, 30, 60, 120};
u8 EEbuf[128];
u16 *ptr = (u16 *)EEbuf, wval = 0;
int i;
carryFlag = 1;
j = 0x80;
for(i=0; i<9; i++)
{
dc390_EEpromOutDI(pdev, regval, carryFlag);
carryFlag = (EEpromCmd & j) ? 1 : 0;
j >>= 1;
}
}
dc390_read_eeprom(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_eepromBuf[index][EE_DELAY] = interpd[dc390_eepromBuf[index][EE_DELAY]];
static void __devinit dc390_ReadEEprom(struct pci_dev *pdev, u16 *ptr)
{
u8 regval,cmd;
u8 i;
for (i = 0; i < 0x40; i++, ptr++)
wval += *ptr;
cmd = EEPROM_READ;
for(i=0; i<0x40; i++)
{
dc390_EnDisableCE(ENABLE_CE, pdev, &regval);
dc390_Prepare(pdev, &regval, cmd++);
*ptr++ = dc390_EEpromGetData1(pdev);
dc390_EnDisableCE(DISABLE_CE, pdev, &regval);
}
}
/* no Tekram EEprom found */
if (wval != 0x1234) {
int speed;
printk(KERN_INFO "DC390_init: No EEPROM found! Trying default settings ...\n");
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]];
}
/*
* XXX(hch): bogus, because we might have tekram and
* non-tekram hbas in a single machine.
*/
dc390_fill_with_defaults();
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);
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]);
}
}
static void __devinit dc390_init_hw(struct dc390_acb *pACB, u8 index)
......@@ -2562,21 +2521,8 @@ static int __devinit dc390_probe_one(struct pci_dev *pdev,
pACB = (struct dc390_acb *)shost->hostdata;
memset(pACB, 0, sizeof(struct dc390_acb));
if (dc390_CheckEEpromCheckSum(pdev, dc390_adapterCnt)) {
int speed;
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);
}
dc390_check_eeprom(pdev, dc390_adapterCnt);
dc390_eeprom_override(dc390_adapterCnt);
io_port = pci_resource_start(pdev, 0);
......@@ -2703,6 +2649,16 @@ static struct pci_driver dc390_driver = {
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);
}
......
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