Commit d3d460df authored by James Bottomley's avatar James Bottomley

Merge raven.il.steeleye.com:/home/jejb/BK/linux-2.5.69

into raven.il.steeleye.com:/home/jejb/BK/scsi-misc-2.5
parents d210257e f99dbcfa
......@@ -371,9 +371,33 @@ The following information is available in this file:
- Fax Technical Support at +852-2869-7100
-------------------------------------------------------------------
(c) 2003 Adaptec, Inc. All Rights Reserved. No part of this
publication may be reproduced, stored in a retrieval system, or
transmitted in any form or by any means, electronic, mechanical,
photocopying, recording or otherwise, without prior written consent
of Adaptec, Inc., 691 South Milpitas Blvd., Milpitas, CA 95035.
/*
* Copyright (c) 2003 Adaptec Inc. 691 S. Milpitas Blvd., Milpitas CA 95035 USA.
* All rights reserved.
*
* You are permitted to redistribute, use and modify this README file in whole
* or in part in conjunction with redistribution of software governed by the
* General Public License, provided that the following conditions are met:
* 1. Redistributions of README file must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
* 3. Modifications or new contributions must be attributed in a copyright
* notice identifying the author ("Contributor") and added below the
* original copyright notice. The copyright notice is for purposes of
* identifying contributors and should not be deemed as permission to alter
* the permissions given by Adaptec.
*
* THIS README FILE IS PROVIDED BY ADAPTEC AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ANY
* WARRANTIES OF NON-INFRINGEMENT OR THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* ADAPTEC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS README
* FILE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
......@@ -132,6 +132,16 @@ The following information is available in this file:
2. Version History
6.2.33 - Dynamically disable PCI parity error reporting after
10 errors are reported to the user. These errors are
the result of some other device issuing PCI transactions
with bad parity. Once the user has been informed of the
problem, continuing to report the errors just degrades
our performance.
6.2.32 - Dynamically sized S/G lists to avoid SCSI malloc
pool fragmentation and SCSI mid-layer deadlock.
6.2.28 - Domain Validation Fixes
PCI parity error disable
Enhanced Memory Mapped I/O probe
......@@ -160,6 +170,7 @@ The following information is available in this file:
Default Value: 0x0000
-----------------------------------------------------------------
Option: no_probe
Option: probe_eisa_vl
Definition: Do not probe for EISA/VLB controllers.
This is a toggle. If the driver is compiled
to not probe EISA/VLB controllers by default,
......@@ -339,9 +350,33 @@ The following information is available in this file:
- Fax Technical Support at +852-2869-7100
-------------------------------------------------------------------
(c) 2002 Adaptec, Inc. All Rights Reserved. No part of this
publication may be reproduced, stored in a retrieval system, or
transmitted in any form or by any means, electronic, mechanical,
photocopying, recording or otherwise, without prior written consent
of Adaptec, Inc., 691 South Milpitas Blvd., Milpitas, CA 95035.
/*
* Copyright (c) 2003 Adaptec Inc. 691 S. Milpitas Blvd., Milpitas CA 95035 USA.
* All rights reserved.
*
* You are permitted to redistribute, use and modify this README file in whole
* or in part in conjunction with redistribution of software governed by the
* General Public License, provided that the following conditions are met:
* 1. Redistributions of README file must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
* 3. Modifications or new contributions must be attributed in a copyright
* notice identifying the author ("Contributor") and added below the
* original copyright notice. The copyright notice is for purposes of
* identifying contributors and should not be deemed as permission to alter
* the permissions given by Adaptec.
*
* THIS README FILE IS PROVIDED BY ADAPTEC AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ANY
* WARRANTIES OF NON-INFRINGEMENT OR THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* ADAPTEC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS README
* FILE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
......@@ -2935,37 +2935,6 @@ int acornscsi_proc_info(char *buffer, char **start, off_t offset,
}
}
p += sprintf(p, "\nAttached devices:\n");
list_for_each_entry(scd, &instance->my_devices, siblings) {
int len;
proc_print_scsidevice(scd, p, &len, 0);
p += len;
p += sprintf(p, "Extensions: ");
if (scd->tagged_supported)
p += sprintf(p, "TAG %sabled [%d] ",
scd->tagged_queue ? "en" : "dis", scd->current_tag);
p += sprintf(p, "\nTransfers: ");
if (host->device[scd->id].sync_xfer & 15)
p += sprintf(p, "sync, offset %d, %d ns\n",
host->device[scd->id].sync_xfer & 15,
acornscsi_getperiod(host->device[scd->id].sync_xfer));
else
p += sprintf(p, "async\n");
pos = p - buffer;
if (pos + begin < offset) {
begin += pos;
p = buffer;
}
pos = p - buffer;
if (pos + begin > offset + length)
break;
}
pos = p - buffer;
*start = buffer + (offset - begin);
......
......@@ -380,26 +380,6 @@ int cumanascsi_2_proc_info (char *buffer, char **start, off_t offset,
pos += sprintf(buffer+pos, "\nAttached devices:\n");
list_for_each_entry(scd, &host->my_devices, siblings) {
int len;
proc_print_scsidevice(scd, buffer, &len, pos);
pos += len;
pos += sprintf(buffer+pos, "Extensions: ");
if (scd->tagged_supported)
pos += sprintf(buffer+pos, "TAG %sabled [%d] ",
scd->tagged_queue ? "en" : "dis",
scd->current_tag);
pos += sprintf(buffer+pos, "\n");
if (pos + begin < offset) {
begin += pos;
pos = 0;
}
if (pos + begin > offset + length)
break;
}
*start = buffer + (offset - begin);
pos -= offset - begin;
if (pos > length)
......
......@@ -452,25 +452,6 @@ int eesoxscsi_proc_info(char *buffer, char **start, off_t offset,
pos += fas216_print_stats(&info->info, buffer + pos);
pos += sprintf(buffer+pos, "\nAttached devices:\n");
list_for_each_entry(scd, &host->my_devices, siblings) {
int len;
proc_print_scsidevice(scd, buffer, &len, pos);
pos += len;
pos += sprintf(buffer+pos, "Extensions: ");
if (scd->tagged_supported)
pos += sprintf(buffer+pos, "TAG %sabled [%d] ",
scd->tagged_queue ? "en" : "dis",
scd->current_tag);
pos += sprintf (buffer+pos, "\n");
if (pos + begin < offset) {
begin += pos;
pos = 0;
}
}
*start = buffer + (offset - begin);
pos -= offset - begin;
if (pos > length)
......
......@@ -299,13 +299,14 @@ static int sg_io(request_queue_t *q, struct block_device *bdev,
#define MOVE_MEDIUM_TIMEOUT (5 * 60 * HZ)
#define READ_ELEMENT_STATUS_TIMEOUT (5 * 60 * HZ)
#define READ_DEFECT_DATA_TIMEOUT (60 * HZ )
#define OMAX_SB_LEN 16 /* For backward compatibility */
static int sg_scsi_ioctl(request_queue_t *q, struct block_device *bdev,
Scsi_Ioctl_Command *sic)
{
struct request *rq;
int err, in_len, out_len, bytes, opcode, cmdlen;
char *buffer = NULL, sense[24];
char *buffer = NULL, sense[SCSI_SENSE_BUFFERSIZE];
/*
* get in an out lengths, verify they don't exceed a page worth of data
......@@ -378,9 +379,12 @@ static int sg_scsi_ioctl(request_queue_t *q, struct block_device *bdev,
blk_do_rq(q, bdev, rq);
err = rq->errors & 0xff; /* only 8 bit SCSI status */
if (err) {
if (rq->sense_len)
if (copy_to_user(sic->data, rq->sense, rq->sense_len))
if (rq->sense_len && rq->sense) {
bytes = (OMAX_SB_LEN > rq->sense_len) ?
rq->sense_len : OMAX_SB_LEN;
if (copy_to_user(sic->data, rq->sense, bytes))
err = -EFAULT;
}
} else {
if (copy_to_user(sic->data, buffer, out_len))
err = -EFAULT;
......
......@@ -3213,6 +3213,7 @@ static void BusLogic_ProcessCompletedCCBs(BusLogic_HostAdapter_T *HostAdapter)
Place CCB back on the Host Adapter's free list.
*/
BusLogic_DeallocateCCB(CCB);
#if 0 /* this needs to be redone different for new EH */
/*
Bus Device Reset CCBs have the Command field non-NULL only when a
Bus Device Reset was requested for a Command that did not have a
......@@ -3228,6 +3229,7 @@ static void BusLogic_ProcessCompletedCCBs(BusLogic_HostAdapter_T *HostAdapter)
Command->scsi_done(Command);
Command = NextCommand;
}
#endif
/*
Iterate over the CCBs for this Host Adapter performing completion
processing for any CCBs marked as Reset for this Target.
......@@ -3948,6 +3950,7 @@ static int BusLogic_ResetHostAdapter(BusLogic_HostAdapter_T *HostAdapter,
{
Command = CCB->Command;
BusLogic_DeallocateCCB(CCB);
#if 0 /* this needs to be redone different for new EH */
while (Command != NULL)
{
SCSI_Command_T *NextCommand = Command->reset_chain;
......@@ -3956,6 +3959,7 @@ static int BusLogic_ResetHostAdapter(BusLogic_HostAdapter_T *HostAdapter,
Command->scsi_done(Command);
Command = NextCommand;
}
#endif
}
for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
{
......@@ -3967,7 +3971,7 @@ static int BusLogic_ResetHostAdapter(BusLogic_HostAdapter_T *HostAdapter,
return Result;
}
#if 0 /* old-style EH code references a dead struct scsi_cmnd member */
/*
BusLogic_SendBusDeviceReset sends a Bus Device Reset to the Target
Device associated with Command.
......@@ -4204,6 +4208,7 @@ int BusLogic_ResetCommand(SCSI_Command_T *Command, unsigned int ResetFlags)
}
return SCSI_RESET_PUNT;
}
#endif
/*
......
......@@ -92,18 +92,12 @@
#define NCR_D700_VERSION "2.2"
#include <linux/config.h>
#include <linux/blk.h>
#include <linux/blkdev.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mca.h>
#include <asm/dma.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/byteorder.h>
#include "scsi.h"
#include "hosts.h"
......@@ -111,16 +105,6 @@
#include "53c700.h"
#include "NCR_D700.h"
#ifndef CONFIG_MCA
#error "NCR_D700 driver only compiles for MCA"
#endif
#ifdef NCR_D700_DEBUG
#define STATIC
#else
#define STATIC static
#endif
char *NCR_D700; /* command line from insmod */
MODULE_AUTHOR("James Bottomley");
......@@ -170,34 +154,101 @@ param_setup(char *string)
return 1;
}
#ifndef MODULE
__setup("NCR_D700=", param_setup);
#endif
/* Host template. The 53c700 routine NCR_700_detect will
* fill in all of the missing routines */
static Scsi_Host_Template NCR_D700_driver_template = {
.module = THIS_MODULE,
.name = "NCR Dual 700 MCA",
.proc_name = "NCR_D700",
.this_id = 7,
};
/* private stack allocated structure for passing device information from
* detect to probe */
struct NCR_700_info {
Scsi_Host_Template *tpnt;
int found;
/* We needs this helper because we have two hosts per struct device */
struct NCR_D700_private {
struct device *dev;
struct Scsi_Host *hosts[2];
};
/* Detect a D700 card. Note, because of the set up---the chips are
static int
NCR_D700_probe_one(struct NCR_D700_private *p, int siop,
int irq, int slot, u32 region, int differential)
{
struct NCR_700_Host_Parameters *hostdata;
struct Scsi_Host *host;
int ret;
hostdata = kmalloc(sizeof(*hostdata), GFP_KERNEL);
if (!hostdata) {
printk(KERN_ERR "NCR D700: SIOP%d: Failed to allocate host"
"data, detatching\n", siop);
return -ENOMEM;
}
memset(hostdata, 0, sizeof(*hostdata));
if (!request_region(region, 64, "NCR_D700")) {
printk(KERN_ERR "NCR D700: Failed to reserve IO region 0x%x\n",
region);
ret = -ENODEV;
goto region_failed;
}
/* Fill in the three required pieces of hostdata */
hostdata->base = region;
hostdata->differential = (((1<<siop) & differential) != 0);
hostdata->clock = NCR_D700_CLOCK_MHZ;
/* and register the siop */
host = NCR_700_detect(&NCR_D700_driver_template, hostdata);
if (!host) {
ret = -ENOMEM;
goto detect_failed;
}
host->irq = irq;
/* FIXME: Read this from SUS */
host->this_id = id_array[slot * 2 + siop];
printk(KERN_NOTICE "NCR D700: SIOP%d, SCSI id is %d\n",
siop, host->this_id);
if (request_irq(irq, NCR_700_intr, SA_SHIRQ, "NCR_D700", host)) {
printk(KERN_ERR "NCR D700: SIOP%d: irq problem, "
"detatching\n", siop);
ret = -ENODEV;
goto irq_failed;
}
scsi_add_host(host, p->dev);
p->hosts[siop] = host;
hostdata->dev = p->dev;
return 0;
irq_failed:
scsi_unregister(host);
NCR_700_release(host);
detect_failed:
release_region(host->base, 64);
region_failed:
kfree(hostdata);
return ret;
}
/* Detect a D700 card. Note, because of the setup --- the chips are
* essentially connectecd to the MCA bus independently, it is easier
* to set them up as two separate host adapters, rather than one
* adapter with two channels */
static int
NCR_D700_probe(struct device *dev)
{
struct NCR_D700_private *p;
int differential;
static int banner = 1;
struct mca_device *mca_dev = to_mca_device(dev);
int slot = mca_dev->slot;
struct NCR_700_info *info = to_mca_driver(dev->driver)->driver_data;
int found = 0;
int irq, i;
int pos3j, pos3k, pos3a, pos3b, pos4;
__u32 base_addr, offset_addr;
struct Scsi_Host *host = NULL;
/* enable board interrupt */
pos4 = mca_device_read_pos(mca_dev, 4);
......@@ -232,8 +283,6 @@ NCR_D700_probe(struct device *dev)
printk(KERN_NOTICE "NCR D700: found in slot %d irq = %d I/O base = 0x%x\n", slot, irq, offset_addr);
info->tpnt->proc_name = "NCR_D700";
/*outb(BOARD_RESET, base_addr);*/
/* clear any pending interrupts */
......@@ -259,70 +308,56 @@ NCR_D700_probe(struct device *dev)
break;
}
p = kmalloc(sizeof(*p), GFP_KERNEL);
if (!p)
return -ENOMEM;
p->dev = dev;
/* plumb in both 700 chips */
for(i=0; i<2; i++) {
__u32 region = offset_addr | (0x80 * i);
struct NCR_700_Host_Parameters *hostdata =
kmalloc(sizeof(struct NCR_700_Host_Parameters),
GFP_KERNEL);
if(hostdata == NULL) {
printk(KERN_ERR "NCR D700: Failed to allocate host data for channel %d, detatching\n", i);
continue;
}
memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters));
if(request_region(region, 64, "NCR_D700") == NULL) {
printk(KERN_ERR "NCR D700: Failed to reserve IO region 0x%x\n", region);
kfree(hostdata);
continue;
}
/* Fill in the three required pieces of hostdata */
hostdata->base = region;
hostdata->differential = (((1<<i) & differential) != 0);
hostdata->clock = NCR_D700_CLOCK_MHZ;
/* and register the chip */
if((host = NCR_700_detect(info->tpnt, hostdata)) == NULL) {
kfree(hostdata);
release_region(host->base, 64);
continue;
}
host->irq = irq;
/* FIXME: Read this from SUS */
host->this_id = id_array[slot * 2 + i];
printk(KERN_NOTICE "NCR D700: SIOP%d, SCSI id is %d\n",
i, host->this_id);
if(request_irq(irq, NCR_700_intr, SA_SHIRQ, "NCR_D700", host)) {
printk(KERN_ERR "NCR D700, channel %d: irq problem, detatching\n", i);
scsi_unregister(host);
NCR_700_release(host);
continue;
}
scsi_set_device(host, dev);
hostdata->dev = dev;
found++;
for (i = 0; i < 2; i++) {
int err;
if ((err = NCR_D700_probe_one(p, i, irq, slot,
offset_addr + (0x80 * i),
differential)) != 0)
printk("D700: SIOP%d: probe failed, error = %d\n",
i, err);
else
found++;
}
info->found += found;
if(found) {
mca_device_set_claim(mca_dev, 1);
strncpy(dev->name, "NCR_D700", sizeof(dev->name));
if (!found) {
kfree(p);
return -ENODEV;
}
return found? 0 : -ENODEV;
mca_device_set_claim(mca_dev, 1);
strncpy(dev->name, "NCR_D700", sizeof(dev->name));
dev_set_drvdata(dev, p);
return 0;
}
STATIC int
D700_release(struct Scsi_Host *host)
static void
NCR_D700_remove_one(struct Scsi_Host *host)
{
struct D700_Host_Parameters *hostdata =
(struct D700_Host_Parameters *)host->hostdata[0];
scsi_remove_host(host);
NCR_700_release(host);
kfree(hostdata);
kfree((struct NCR_700_Host_Parameters *)host->hostdata[0]);
free_irq(host->irq, host);
release_region(host->base, 64);
return 1;
}
static int
NCR_D700_remove(struct device *dev)
{
struct NCR_D700_private *p = dev_get_drvdata(dev);
int i;
for (i = 0; i < 2; i++)
NCR_D700_remove_one(p->hosts[i]);
kfree(p);
return 0;
}
static short NCR_D700_id_table[] = { NCR_D700_MCA_ID, 0 };
......@@ -330,34 +365,29 @@ static short NCR_D700_id_table[] = { NCR_D700_MCA_ID, 0 };
struct mca_driver NCR_D700_driver = {
.id_table = NCR_D700_id_table,
.driver = {
.name = "NCR_D700",
.bus = &mca_bus_type,
.probe = NCR_D700_probe,
.name = "NCR_D700",
.bus = &mca_bus_type,
.probe = NCR_D700_probe,
.remove = NCR_D700_remove,
},
};
STATIC int __init
D700_detect(Scsi_Host_Template *tpnt)
static int __init NCR_D700_init(void)
{
struct NCR_700_info info;
if(!MCA_bus)
return 0;
#ifdef MODULE
if(NCR_D700)
if (NCR_D700)
param_setup(NCR_D700);
#endif
info.tpnt = tpnt;
info.found = 0;
NCR_D700_driver.driver_data = &info;
mca_register_driver(&NCR_D700_driver);
return info.found;
return mca_register_driver(&NCR_D700_driver);
}
static void __exit NCR_D700_exit(void)
{
mca_unregister_driver(&NCR_D700_driver);
}
static Scsi_Host_Template driver_template = NCR_D700_SCSI;
#include "scsi_module.c"
module_init(NCR_D700_init);
module_exit(NCR_D700_exit);
__setup("NCR_D700=", param_setup);
......@@ -14,22 +14,6 @@
/* The MCA identifier */
#define NCR_D700_MCA_ID 0x0092
static int D700_detect(Scsi_Host_Template *);
static int D700_release(struct Scsi_Host *host);
/* Host template. Note the name and proc_name are optional, all the
* remaining parameters shown below must be filled in. The 53c700
* routine NCR_700_detect will fill in all of the missing routines */
#define NCR_D700_SCSI { \
.name = "NCR Dual 700 MCA", \
.proc_name = "NCR_D700", \
.detect = D700_detect, \
.release = D700_release, \
.this_id = 7, \
}
/* Defines for the Board registers */
#define BOARD_RESET 0x80 /* board level reset */
#define ADD_PARENB 0x04 /* Address Parity Enabled */
......
......@@ -37,7 +37,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* $Id: //depot/aic7xxx/aic7xxx/aic7770.c#29 $
* $Id: //depot/aic7xxx/aic7xxx/aic7770.c#30 $
*
* $FreeBSD$
*/
......@@ -314,7 +314,7 @@ aha2840_load_seeprom(struct ahc_softc *ahc)
if (bootverbose)
printf("%s: Reading SEEPROM...", ahc_name(ahc));
have_seeprom = ahc_read_seeprom(&sd, (uint16_t *)sc,
/*start_addr*/0, sizeof(sc)/2);
/*start_addr*/0, sizeof(*sc)/2);
if (have_seeprom) {
......
......@@ -37,7 +37,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#88 $
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#89 $
*
* $FreeBSD$
*/
......@@ -494,13 +494,11 @@ struct hardware_scb {
* transfer.
*/
#define SG_PTR_MASK 0xFFFFFFF8
/*16*/ uint16_t tag;
/*18*/ uint8_t cdb_len;
/*19*/ uint8_t task_management;
/*20*/ uint32_t next_hscb_busaddr;
/*24*/ uint64_t dataptr;
/*32*/ uint32_t datacnt; /* Byte 3 is spare. */
/*36*/ uint32_t sgptr;
/*16*/ uint64_t dataptr;
/*24*/ uint32_t datacnt; /* Byte 3 is spare. */
/*28*/ uint32_t sgptr;
/*32*/ uint32_t hscb_busaddr;
/*36*/ uint32_t next_hscb_busaddr;
/*40*/ uint8_t control; /* See SCB_CONTROL in aic79xx.reg for details */
/*41*/ uint8_t scsiid; /*
* Selection out Id
......@@ -508,8 +506,10 @@ struct hardware_scb {
*/
/*42*/ uint8_t lun;
/*43*/ uint8_t task_attribute;
/*44*/ uint32_t hscb_busaddr;
/******* Long lun field only downloaded for full 8 byte lun support *******/
/*44*/ uint8_t cdb_len;
/*45*/ uint8_t task_management;
/*46*/ uint16_t tag; /* Reused by Sequencer. */
/********** Long lun field only downloaded for full 8 byte lun support ********/
/*48*/ uint8_t pkt_long_lun[8];
/******* Fields below are not Downloaded (Sequencer may use for scratch) ******/
/*56*/ uint8_t spare[8];
......
......@@ -39,7 +39,7 @@
*
* $FreeBSD$
*/
VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#65 $"
VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#67 $"
/*
* This file is processed by the aic7xxx_asm utility for use in assembling
......@@ -194,7 +194,8 @@ register SEQINTCODE {
TRACEPOINT1,
TRACEPOINT2,
TRACEPOINT3,
SAW_HWERR
SAW_HWERR,
BAD_SCB_STATUS
}
}
......@@ -3484,9 +3485,6 @@ scratch_ram {
LONGJMP_ADDR {
size 2
}
LONGJMP_SCB {
size 2
}
ACCUM_SAVE {
size 1
}
......@@ -3799,23 +3797,6 @@ scb {
size 4
alias SCB_NEXT_COMPLETE
}
SCB_TAG {
size 2
}
SCB_CDB_LEN {
size 1
field SCB_CDB_LEN_PTR 0x80 /* CDB in host memory */
}
SCB_TASK_MANAGEMENT {
size 1
}
SCB_NEXT {
alias SCB_NEXT_SCB_BUSADDR
size 2
}
SCB_NEXT2 {
size 2
}
SCB_DATAPTR {
size 8
}
......@@ -3834,6 +3815,16 @@ scb {
field SG_FULL_RESID 0x02 /* In the first byte */
field SG_LIST_NULL 0x01 /* In the first byte */
}
SCB_BUSADDR {
size 4
}
SCB_NEXT {
alias SCB_NEXT_SCB_BUSADDR
size 2
}
SCB_NEXT2 {
size 2
}
SCB_CONTROL {
size 1
field TARGET_SCB 0x80
......@@ -3856,8 +3847,16 @@ scb {
SCB_TASK_ATTRIBUTE {
size 1
}
SCB_BUSADDR {
size 4
SCB_CDB_LEN {
size 1
field SCB_CDB_LEN_PTR 0x80 /* CDB in host memory */
}
SCB_TASK_MANAGEMENT {
size 1
}
SCB_TAG {
alias SCB_FIFO_USE_COUNT
size 2
}
SCB_SPARE {
size 8
......
This diff is collapsed.
......@@ -37,7 +37,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#178 $
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#190 $
*
* $FreeBSD$
*/
......@@ -556,6 +556,26 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
ahd_name(ahd), seqintcode);
#endif
switch (seqintcode) {
case BAD_SCB_STATUS:
{
struct scb *scb;
u_int scbid;
int cmds_pending;
scbid = ahd_get_scbptr(ahd);
scb = ahd_lookup_scb(ahd, scbid);
if (scb != NULL) {
ahd_complete_scb(ahd, scb);
} else {
printf("%s: WARNING no command for scb %d "
"(bad status)\n", ahd_name(ahd), scbid);
ahd_dump_card_state(ahd);
}
cmds_pending = ahd_inw(ahd, CMDS_PENDING);
if (cmds_pending > 0)
ahd_outw(ahd, CMDS_PENDING, cmds_pending - 1);
break;
}
case ENTERING_NONPACK:
{
struct scb *scb;
......@@ -604,7 +624,16 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
break;
case STATUS_OVERRUN:
{
printf("%s: Status Overrun", ahd_name(ahd));
struct scb *scb;
u_int scbid;
scbid = ahd_get_scbptr(ahd);
scb = ahd_lookup_scb(ahd, scbid);
if (scb != NULL)
ahd_print_path(ahd, scb);
else
printf("%s: ", ahd_name(ahd));
printf("SCB %d Packetized Status Overrun", scbid);
ahd_dump_card_state(ahd);
ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
break;
......@@ -1023,7 +1052,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
switch (scb->hscb->task_management) {
case SIU_TASKMGMT_ABORT_TASK:
tag = scb->hscb->tag;
tag = SCB_GET_TAG(scb);
case SIU_TASKMGMT_ABORT_TASK_SET:
case SIU_TASKMGMT_CLEAR_TASK_SET:
lun = scb->hscb->lun;
......@@ -1087,7 +1116,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
ahd_outb(ahd, SCB_TASK_MANAGEMENT, 0);
ahd_search_qinfifo(ahd, SCB_GET_TARGET(ahd, scb),
SCB_GET_CHANNEL(ahd, scb),
SCB_GET_LUN(scb), scb->hscb->tag,
SCB_GET_LUN(scb), SCB_GET_TAG(scb),
ROLE_INITIATOR, /*status*/0,
SEARCH_REMOVE);
}
......@@ -1166,7 +1195,7 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
/*
* A change in I/O mode is equivalent to a bus reset.
*/
ahd_reset_channel(ahd, 'A', /*Initiate Reset*/FALSE);
ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
ahd_pause(ahd);
ahd_setup_iocell_workaround(ahd);
ahd_unpause(ahd);
......@@ -2183,6 +2212,13 @@ ahd_clear_critical_section(struct ahd_softc *ahd)
ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
ahd_outb(ahd, SEQCTL0, ahd_inb(ahd, SEQCTL0) & ~STEP);
ahd_outb(ahd, SIMODE1, simode1);
/*
* SCSIINT seems to glitch occassionally when
* the interrupt masks are restored. Clear SCSIINT
* one more time so that only persistent errors
* are seen as a real interrupt.
*/
ahd_outb(ahd, CLRINT, CLRSCSIINT);
}
ahd_restore_modes(ahd, saved_modes);
}
......@@ -4887,7 +4923,6 @@ ahd_free(struct ahd_softc *ahd)
{
int i;
ahd_fini_scbdata(ahd);
switch (ahd->init_level) {
default:
case 5:
......@@ -4919,6 +4954,7 @@ ahd_free(struct ahd_softc *ahd)
ahd_dma_tag_destroy(ahd, ahd->parent_dmat);
#endif
ahd_platform_free(ahd);
ahd_fini_scbdata(ahd);
for (i = 0; i < AHD_NUM_TARGETS; i++) {
struct ahd_tmode_tstate *tstate;
......@@ -5481,7 +5517,7 @@ ahd_free_scb(struct ahd_softc *ahd, struct scb *scb)
/* Clean up for the next user */
scb->flags = SCB_FLAG_NONE;
scb->hscb->control = 0;
ahd->scb_data.scbindex[scb->hscb->tag] = NULL;
ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = NULL;
if (scb->col_scb == NULL) {
......@@ -5584,8 +5620,8 @@ ahd_alloc_scbs(struct ahd_softc *ahd)
if (scb_data->sgs_left != 0) {
int offset;
offset = ahd_sglist_allocsize(ahd)
- (scb_data->sgs_left * ahd_sglist_size(ahd));
offset = ((ahd_sglist_allocsize(ahd) / ahd_sglist_size(ahd))
- scb_data->sgs_left) * ahd_sglist_size(ahd);
sg_map = SLIST_FIRST(&scb_data->sg_maps);
segs = sg_map->vaddr + offset;
sg_busaddr = sg_map->physaddr + offset;
......@@ -5894,7 +5930,7 @@ ahd_init(struct ahd_softc *ahd)
* specially from the DMA safe memory chunk used for the QOUTFIFO.
*/
ahd->next_queued_hscb = (struct hardware_scb *)next_vaddr;
ahd->next_queued_hscb->hscb_busaddr = next_baddr;
ahd->next_queued_hscb->hscb_busaddr = ahd_htole32(next_baddr);
ahd->init_level++;
......@@ -6056,7 +6092,6 @@ ahd_chip_init(struct ahd_softc *ahd)
for (i = 0; i < 2; i++) {
ahd_set_modes(ahd, AHD_MODE_DFF0 + i, AHD_MODE_DFF0 + i);
ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR);
ahd_outw(ahd, LONGJMP_SCB, SCB_LIST_NULL);
ahd_outb(ahd, SG_STATE, 0);
ahd_outb(ahd, CLRSEQINTSRC, 0xFF);
ahd_outb(ahd, SEQIMODE,
......@@ -6605,24 +6640,29 @@ ahd_enable_coalessing(struct ahd_softc *ahd, int enable)
void
ahd_pause_and_flushwork(struct ahd_softc *ahd)
{
ahd_mode_state saved_modes;
u_int intstat;
u_int maxloops;
int paused;
u_int intstat;
u_int maxloops;
u_int qfreeze_cnt;
maxloops = 1000;
ahd->flags |= AHD_ALL_INTERRUPTS;
paused = FALSE;
ahd_pause(ahd);
/*
* Increment the QFreeze Count so that the sequencer
* will not start new selections. We do this only
* until we are safely paused without further selections
* pending.
*/
ahd_outw(ahd, QFREEZE_COUNT, ahd_inw(ahd, QFREEZE_COUNT) + 1);
ahd_outb(ahd, SEQ_FLAGS2, ahd_inb(ahd, SEQ_FLAGS2) | SELECTOUT_QFROZEN);
do {
struct scb *waiting_scb;
if (paused)
ahd_unpause(ahd);
ahd_unpause(ahd);
ahd_intr(ahd);
ahd_pause(ahd);
paused = TRUE;
ahd_clear_critical_section(ahd);
saved_modes = ahd_save_modes(ahd);
intstat = ahd_inb(ahd, INTSTAT);
ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
if ((ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) == 0)
ahd_outb(ahd, SCSISEQ0,
......@@ -6639,22 +6679,32 @@ ahd_pause_and_flushwork(struct ahd_softc *ahd)
&& (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) != 0)
ahd_outb(ahd, SCSISEQ0,
ahd_inb(ahd, SCSISEQ0) | ENSELO);
intstat = ahd_inb(ahd, INTSTAT);
} while (--maxloops
&& (intstat != 0xFF || (ahd->features & AHD_REMOVABLE) == 0)
&& ((intstat & INT_PEND) != 0
|| (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO))));
|| (ahd_inb(ahd, SCSISEQ0) & ENSELO) != 0
|| (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) != 0));
if (maxloops == 0) {
printf("Infinite interrupt loop, INTSTAT = %x",
ahd_inb(ahd, INTSTAT));
}
qfreeze_cnt = ahd_inw(ahd, QFREEZE_COUNT);
if (qfreeze_cnt == 0) {
printf("%s: ahd_pause_and_flushwork with 0 qfreeze count!\n",
ahd_name(ahd));
} else {
qfreeze_cnt--;
}
ahd_outw(ahd, QFREEZE_COUNT, qfreeze_cnt);
if (qfreeze_cnt == 0)
ahd_outb(ahd, SEQ_FLAGS2,
ahd_inb(ahd, SEQ_FLAGS2) & ~SELECTOUT_QFROZEN);
ahd_flush_qoutfifo(ahd);
ahd_platform_flushwork(ahd);
ahd->flags &= ~AHD_ALL_INTERRUPTS;
ahd_restore_modes(ahd, saved_modes);
}
int
......@@ -7514,14 +7564,17 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
ahd_outb(ahd, DFFSTAT, next_fifo);
} while (next_fifo != fifo);
/*
* Reset the bus if we are initiating this reset
*/
ahd_clear_msg_state(ahd);
ahd_outb(ahd, SIMODE1,
ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST|ENBUSFREE));
if (initiate_reset)
ahd_reset_current_bus(ahd);
ahd_clear_intstat(ahd);
/*
......@@ -7719,9 +7772,6 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb)
hscb = scb->hscb;
/* Freeze the queue until the client sees the error. */
ahd_pause(ahd);
ahd_clear_critical_section(ahd);
ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
ahd_freeze_devq(ahd, scb);
ahd_freeze_scb(scb);
qfreeze_cnt = ahd_inw(ahd, QFREEZE_COUNT);
......@@ -7734,7 +7784,7 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb)
if (qfreeze_cnt == 0)
ahd_outb(ahd, SEQ_FLAGS2,
ahd_inb(ahd, SEQ_FLAGS2) & ~SELECTOUT_QFROZEN);
ahd_unpause(ahd);
/* Don't want to clobber the original sense code */
if ((scb->flags & SCB_SENSE) != 0) {
/*
......@@ -8592,11 +8642,11 @@ ahd_dump_card_state(struct ahd_softc *ahd)
LIST_FOREACH(scb, &ahd->pending_scbs, pending_links) {
if (i++ > AHD_SCB_MAX)
break;
cur_col = printf("\n%3d ", SCB_GET_TAG(scb));
cur_col = printf("\n%3d FIFO_USE[0x%x] ", SCB_GET_TAG(scb),
ahd_inb(ahd, SCB_FIFO_USE_COUNT));
ahd_set_scbptr(ahd, SCB_GET_TAG(scb));
ahd_scb_control_print(ahd_inb(ahd, SCB_CONTROL), &cur_col, 60);
ahd_scb_scsiid_print(ahd_inb(ahd, SCB_SCSIID), &cur_col, 60);
ahd_scb_tag_print(ahd_inb(ahd, SCB_TAG), &cur_col, 60);
}
printf("\nTotal %d\n", i);
......@@ -8659,12 +8709,10 @@ ahd_dump_card_state(struct ahd_softc *ahd)
ahd_set_modes(ahd, AHD_MODE_DFF0 + i, AHD_MODE_DFF0 + i);
fifo_scbptr = ahd_get_scbptr(ahd);
printf("\n%s: FIFO%d %s, LONGJMP == 0x%x, "
"SCB 0x%x, LJSCB 0x%x\n",
printf("\n%s: FIFO%d %s, LONGJMP == 0x%x, SCB 0x%x\n",
ahd_name(ahd), i,
(dffstat & (FIFO0FREE << i)) ? "Free" : "Active",
ahd_inw(ahd, LONGJMP_ADDR), fifo_scbptr,
ahd_inw(ahd, LONGJMP_SCB));
ahd_inw(ahd, LONGJMP_ADDR), fifo_scbptr);
cur_col = 0;
ahd_seqimode_print(ahd_inb(ahd, SEQIMODE), &cur_col, 50);
ahd_seqintsrc_print(ahd_inb(ahd, SEQINTSRC), &cur_col, 50);
......
......@@ -37,7 +37,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#44 $
* $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#48 $
*
* $FreeBSD$
*/
......@@ -223,7 +223,7 @@ ahd_unpause(struct ahd_softc *ahd)
ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode);
}
if ((ahd_inb(ahd, INTSTAT) & ~(SWTMINT | CMDCMPLT)) == 0)
if ((ahd_inb(ahd, INTSTAT) & ~CMDCMPLT) == 0)
ahd_outb(ahd, HCNTRL, ahd->unpause);
ahd_known_modes(ahd, AHD_MODE_UNKNOWN, AHD_MODE_UNKNOWN);
......@@ -298,9 +298,12 @@ ahd_setup_data_scb(struct ahd_softc *ahd, struct scb *scb)
scb->hscb->datacnt = sg->len;
} else {
struct ahd_dma_seg *sg;
uint32_t *dataptr_words;
sg = (struct ahd_dma_seg *)scb->sg_list;
scb->hscb->dataptr = sg->addr;
dataptr_words = (uint32_t*)&scb->hscb->dataptr;
dataptr_words[0] = sg->addr;
dataptr_words[1] = 0;
if ((ahd->flags & AHD_39BIT_ADDRESSING) != 0) {
uint64_t high_addr;
......@@ -777,12 +780,15 @@ ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb)
#ifdef AHD_DEBUG
if ((ahd_debug & AHD_SHOW_QUEUE) != 0) {
uint64_t host_dataptr;
host_dataptr = ahd_le64toh(scb->hscb->dataptr);
printf("%s: Queueing SCB 0x%x bus addr 0x%x - 0x%x%x/0x%x\n",
ahd_name(ahd),
SCB_GET_TAG(scb), scb->hscb->hscb_busaddr,
(u_int)((scb->hscb->dataptr >> 32) & 0xFFFFFFFF),
(u_int)(scb->hscb->dataptr & 0xFFFFFFFF),
scb->hscb->datacnt);
SCB_GET_TAG(scb), ahd_le32toh(scb->hscb->hscb_busaddr),
(u_int)((host_dataptr >> 32) & 0xFFFFFFFF),
(u_int)(host_dataptr & 0xFFFFFFFF),
ahd_le32toh(scb->hscb->datacnt));
}
#endif
/* Tell the adapter about the newly queued SCB */
......@@ -805,7 +811,7 @@ ahd_get_sense_bufaddr(struct ahd_softc *ahd, struct scb *scb)
static __inline void ahd_sync_qoutfifo(struct ahd_softc *ahd, int op);
static __inline void ahd_sync_tqinfifo(struct ahd_softc *ahd, int op);
static __inline u_int ahd_check_cmdcmpltqueues(struct ahd_softc *ahd);
static __inline void ahd_intr(struct ahd_softc *ahd);
static __inline int ahd_intr(struct ahd_softc *ahd);
static __inline void
ahd_sync_qoutfifo(struct ahd_softc *ahd, int op)
......@@ -864,7 +870,7 @@ ahd_check_cmdcmpltqueues(struct ahd_softc *ahd)
/*
* Catch an interrupt from the adapter
*/
static __inline void
static __inline int
ahd_intr(struct ahd_softc *ahd)
{
u_int intstat;
......@@ -876,7 +882,7 @@ ahd_intr(struct ahd_softc *ahd)
* so just return. This is likely just a shared
* interrupt.
*/
return;
return (0);
}
/*
......@@ -891,6 +897,9 @@ ahd_intr(struct ahd_softc *ahd)
else
intstat = ahd_inb(ahd, INTSTAT);
if ((intstat & INT_PEND) == 0)
return (0);
if (intstat & CMDCMPLT) {
ahd_outb(ahd, CLRINT, CLRCMDINT);
......@@ -924,28 +933,25 @@ ahd_intr(struct ahd_softc *ahd)
#endif
}
if (intstat == 0xFF && (ahd->features & AHD_REMOVABLE) != 0)
/* Hot eject */
return;
if ((intstat & INT_PEND) == 0)
return;
if (intstat & HWERRINT) {
/*
* Handle statuses that may invalidate our cached
* copy of INTSTAT separately.
*/
if (intstat == 0xFF && (ahd->features & AHD_REMOVABLE) != 0) {
/* Hot eject. Do nothing */
} else if (intstat & HWERRINT) {
ahd_handle_hwerrint(ahd);
return;
}
if ((intstat & (PCIINT|SPLTINT)) != 0) {
} else if ((intstat & (PCIINT|SPLTINT)) != 0) {
ahd->bus_intr(ahd);
return;
}
} else {
if ((intstat & SEQINT) != 0)
ahd_handle_seqint(ahd, intstat);
if ((intstat & SEQINT) != 0)
ahd_handle_seqint(ahd, intstat);
if ((intstat & SCSIINT) != 0)
ahd_handle_scsiint(ahd, intstat);
if ((intstat & SCSIINT) != 0)
ahd_handle_scsiint(ahd, intstat);
}
return (1);
}
#endif /* _AIC79XX_INLINE_H_ */
This diff is collapsed.
......@@ -36,7 +36,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.h#121 $
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.h#130 $
*
*/
#ifndef _AIC79XX_LINUX_H_
......@@ -139,7 +139,7 @@ typedef Scsi_Cmnd *ahd_io_ctx_t;
#endif /* BYTE_ORDER */
/************************* Configuration Data *********************************/
extern int aic79xx_allow_memio;
extern uint32_t aic79xx_allow_memio;
extern int aic79xx_detect_complete;
extern Scsi_Host_Template aic79xx_driver_template;
......@@ -255,7 +255,7 @@ typedef struct timer_list ahd_timer_t;
/***************************** Timer Facilities *******************************/
#define ahd_timer_init init_timer
#define ahd_timer_stop del_timer
#define ahd_timer_stop del_timer_sync
typedef void ahd_linux_callback_t (u_long);
static __inline void ahd_timer_reset(ahd_timer_t *timer, u_int usec,
ahd_callback_t *func, void *arg);
......@@ -293,7 +293,7 @@ ahd_scb_timer_reset(struct scb *scb, u_int usec)
#define AHD_SCSI_HAS_HOST_LOCK 0
#endif
#define AIC79XX_DRIVER_VERSION "1.3.5"
#define AIC79XX_DRIVER_VERSION "1.3.8"
/**************************** Front End Queues ********************************/
/*
......@@ -488,7 +488,18 @@ struct ahd_linux_target {
* manner and are allocated below 4GB, the number of S/G segments is
* unrestricted.
*/
#define AHD_NSEG 128
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
/*
* We dynamically adjust the number of segments in pre-2.5 kernels to
* avoid fragmentation issues in the SCSI mid-layer's private memory
* allocator. See aic79xx_osm.c ahd_linux_size_nseg() for details.
*/
extern u_int ahd_linux_nseg;
#define AHD_NSEG ahd_linux_nseg
#define AHD_LINUX_MIN_NSEG 64
#else
#define AHD_NSEG 128
#endif
/*
* Per-SCB OSM storage.
......@@ -532,9 +543,7 @@ struct ahd_platform_data {
TAILQ_HEAD(, ahd_linux_device) device_runq;
struct ahd_completeq completeq;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,93)
spinlock_t spin_lock;
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
struct tasklet_struct runq_tasklet;
#endif
......@@ -730,7 +739,6 @@ static __inline void ahd_list_lockinit(void);
static __inline void ahd_list_lock(unsigned long *flags);
static __inline void ahd_list_unlock(unsigned long *flags);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,93)
static __inline void
ahd_lockinit(struct ahd_softc *ahd)
{
......@@ -818,63 +826,6 @@ ahd_list_unlock(unsigned long *flags)
spin_unlock_irqrestore(&ahd_list_spinlock, *flags);
}
#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) */
ahd_lockinit(struct ahd_softc *ahd)
{
}
static __inline void
ahd_lock(struct ahd_softc *ahd, unsigned long *flags)
{
save_flags(*flags);
cli();
}
static __inline void
ahd_unlock(struct ahd_softc *ahd, unsigned long *flags)
{
restore_flags(*flags);
}
ahd_done_lockinit(struct ahd_softc *ahd)
{
}
static __inline void
ahd_done_lock(struct ahd_softc *ahd, unsigned long *flags)
{
/*
* The done lock is always held while
* the ahd lock is held so blocking
* interrupts again would have no effect.
*/
}
static __inline void
ahd_done_unlock(struct ahd_softc *ahd, unsigned long *flags)
{
}
static __inline void
ahd_list_lockinit()
{
}
static __inline void
ahd_list_lock(unsigned long *flags)
{
save_flags(*flags);
cli();
}
static __inline void
ahd_list_unlock(unsigned long *flags)
{
restore_flags(*flags);
}
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) */
/******************************* PCI Definitions ******************************/
/*
* PCIM_xxx: mask to locate subfield in register
......@@ -945,16 +896,6 @@ void ahd_power_state_change(struct ahd_softc *ahd,
ahd_power_state new_state);
/******************************* PCI Routines *********************************/
/*
* We need to use the bios32.h routines if we are kernel version 2.1.92 or less.
*/
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,1,92)
#if defined(__sparc_v9__) || defined(__powerpc__)
#error "PPC and Sparc platforms are only supported under 2.1.92 and above"
#endif
#include <linux/bios32.h>
#endif
int ahd_linux_pci_init(void);
void ahd_linux_pci_exit(void);
int ahd_pci_map_registers(struct ahd_softc *ahd);
......@@ -1270,7 +1211,8 @@ void ahd_platform_set_tags(struct ahd_softc *ahd,
int ahd_platform_abort_scbs(struct ahd_softc *ahd, int target,
char channel, int lun, u_int tag,
role_t role, uint32_t status);
void ahd_linux_isr(int irq, void *dev_id, struct pt_regs * regs);
AIC_LINUX_IRQRETURN_T
ahd_linux_isr(int irq, void *dev_id, struct pt_regs * regs);
void ahd_platform_flushwork(struct ahd_softc *ahd);
int ahd_softc_comp(struct ahd_softc *, struct ahd_softc *);
void ahd_done(struct ahd_softc*, struct scb*);
......@@ -1285,5 +1227,5 @@ void ahd_platform_dump_card_state(struct ahd_softc *ahd);
#define AHD_PCI_CONFIG 0
#endif
#define bootverbose aic79xx_verbose
extern int aic79xx_verbose;
extern uint32_t aic79xx_verbose;
#endif /* _AIC79XX_LINUX_H_ */
......@@ -38,7 +38,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#70 $
* $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#71 $
*
* $FreeBSD$
*/
......@@ -565,14 +565,13 @@ ahd_check_extport(struct ahd_softc *ahd)
#if AHD_DEBUG
if (have_seeprom != 0
&& (ahd_debug & AHD_DUMP_SEEPROM) != 0) {
uint8_t *sc_data;
int i;
uint16_t *sc_data;
int i;
printf("%s: Seeprom Contents:", ahd_name(ahd));
sc_data = (uint8_t *)sc;
sc_data = (uint16_t *)sc;
for (i = 0; i < (sizeof(*sc)); i += 2)
printf("\n\t0x%.4x",
sc_data[i] | (sc_data[i+1] << 8));
printf("\n\t0x%.4x", sc_data[i]);
printf("\n");
}
#endif
......
......@@ -37,7 +37,7 @@
* String handling code courtesy of Gerard Roudier's <groudier@club-internet.fr>
* sym driver.
*
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_proc.c#14 $
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_proc.c#17 $
*/
#include "aic79xx_osm.h"
#include "aic79xx_inline.h"
......@@ -173,8 +173,7 @@ ahd_dump_target_state(struct ahd_softc *ahd, struct info_str *info,
tinfo = ahd_fetch_transinfo(ahd, channel, our_id,
target_id, &tstate);
copy_info(info, "Channel %c Target %d Negotiation Settings\n",
channel, target_id);
copy_info(info, "Target %d Negotiation Settings\n", target_id);
copy_info(info, "\tUser: ");
ahd_format_transinfo(info, &tinfo->user);
targ = ahd->platform_data->targets[target_offset];
......@@ -318,7 +317,11 @@ ahd_linux_proc_info(char *buffer, char **start, off_t offset,
AIC79XX_DRIVER_VERSION);
copy_info(&info, "%s\n", ahd->description);
ahd_controller_info(ahd, ahd_info);
copy_info(&info, "%s\n\n", ahd_info);
copy_info(&info, "%s\n", ahd_info);
copy_info(&info, "Allocated SCBs: %d, SG List Length: %d\n\n",
ahd->scb_data.numscbs, AHD_NSEG);
max_targ = 15;
if (ahd->seep_config == NULL)
copy_info(&info, "No Serial EEPROM\n");
......@@ -335,7 +338,6 @@ ahd_linux_proc_info(char *buffer, char **start, off_t offset,
}
copy_info(&info, "\n");
max_targ = 15;
if ((ahd->features & AHD_WIDE) == 0)
max_targ = 7;
......
......@@ -2,8 +2,8 @@
* DO NOT EDIT - This file is automatically generated
* from the following source files:
*
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#89 $
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#65 $
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#91 $
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#67 $
*/
typedef int (ahd_reg_print_t)(u_int, u_int *, u_int);
typedef struct ahd_reg_parse_entry {
......@@ -1923,18 +1923,11 @@ ahd_reg_print_t ahd_longjmp_addr_print;
ahd_print_register(NULL, 0, "LONGJMP_ADDR", 0xf8, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_longjmp_scb_print;
#else
#define ahd_longjmp_scb_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "LONGJMP_SCB", 0xfa, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_accum_save_print;
#else
#define ahd_accum_save_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "ACCUM_SAVE", 0xfc, regvalue, cur_col, wrap)
ahd_print_register(NULL, 0, "ACCUM_SAVE", 0xfa, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
......@@ -2246,59 +2239,45 @@ ahd_reg_print_t ahd_scb_sense_busaddr_print;
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_scb_tag_print;
#else
#define ahd_scb_tag_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "SCB_TAG", 0x190, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_scb_cdb_len_print;
#else
#define ahd_scb_cdb_len_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "SCB_CDB_LEN", 0x192, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_scb_task_management_print;
ahd_reg_print_t ahd_scb_dataptr_print;
#else
#define ahd_scb_task_management_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "SCB_TASK_MANAGEMENT", 0x193, regvalue, cur_col, wrap)
#define ahd_scb_dataptr_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "SCB_DATAPTR", 0x190, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_scb_next_print;
ahd_reg_print_t ahd_scb_datacnt_print;
#else
#define ahd_scb_next_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "SCB_NEXT", 0x194, regvalue, cur_col, wrap)
#define ahd_scb_datacnt_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "SCB_DATACNT", 0x198, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_scb_next2_print;
ahd_reg_print_t ahd_scb_sgptr_print;
#else
#define ahd_scb_next2_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "SCB_NEXT2", 0x196, regvalue, cur_col, wrap)
#define ahd_scb_sgptr_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "SCB_SGPTR", 0x19c, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_scb_dataptr_print;
ahd_reg_print_t ahd_scb_busaddr_print;
#else
#define ahd_scb_dataptr_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "SCB_DATAPTR", 0x198, regvalue, cur_col, wrap)
#define ahd_scb_busaddr_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "SCB_BUSADDR", 0x1a0, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_scb_datacnt_print;
ahd_reg_print_t ahd_scb_next_print;
#else
#define ahd_scb_datacnt_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "SCB_DATACNT", 0x1a0, regvalue, cur_col, wrap)
#define ahd_scb_next_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "SCB_NEXT", 0x1a4, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_scb_sgptr_print;
ahd_reg_print_t ahd_scb_next2_print;
#else
#define ahd_scb_sgptr_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "SCB_SGPTR", 0x1a4, regvalue, cur_col, wrap)
#define ahd_scb_next2_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "SCB_NEXT2", 0x1a6, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
......@@ -2330,10 +2309,24 @@ ahd_reg_print_t ahd_scb_task_attribute_print;
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_scb_busaddr_print;
ahd_reg_print_t ahd_scb_cdb_len_print;
#else
#define ahd_scb_busaddr_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "SCB_BUSADDR", 0x1ac, regvalue, cur_col, wrap)
#define ahd_scb_cdb_len_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "SCB_CDB_LEN", 0x1ac, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_scb_task_management_print;
#else
#define ahd_scb_task_management_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "SCB_TASK_MANAGEMENT", 0x1ad, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_scb_tag_print;
#else
#define ahd_scb_tag_print(regvalue, cur_col, wrap) \
ahd_print_register(NULL, 0, "SCB_TAG", 0x1ae, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
......@@ -2367,6 +2360,7 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define SPLTINT 0x01
#define SEQINTCODE 0x02
#define BAD_SCB_STATUS 0x1a
#define SAW_HWERR 0x19
#define TRACEPOINT3 0x18
#define TRACEPOINT2 0x17
......@@ -3508,9 +3502,7 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define LONGJMP_ADDR 0xf8
#define LONGJMP_SCB 0xfa
#define ACCUM_SAVE 0xfc
#define ACCUM_SAVE 0xfa
#define WAITING_SCB_TAILS 0x100
......@@ -3656,29 +3648,24 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define SCB_SENSE_BUSADDR 0x18c
#define SCB_NEXT_COMPLETE 0x18c
#define SCB_TAG 0x190
#define SCB_CDB_LEN 0x192
#define SCB_CDB_LEN_PTR 0x80
#define SCB_TASK_MANAGEMENT 0x193
#define SCB_NEXT 0x194
#define SCB_NEXT_SCB_BUSADDR 0x194
#define SCB_DATAPTR 0x190
#define SCB_NEXT2 0x196
#define SCB_DATAPTR 0x198
#define SCB_DATACNT 0x1a0
#define SCB_DATACNT 0x198
#define SG_LAST_SEG 0x80
#define SG_HIGH_ADDR_BITS 0x7f
#define SCB_SGPTR 0x1a4
#define SCB_SGPTR 0x19c
#define SG_STATUS_VALID 0x04
#define SG_FULL_RESID 0x02
#define SG_LIST_NULL 0x01
#define SCB_BUSADDR 0x1a0
#define SCB_NEXT 0x1a4
#define SCB_NEXT_SCB_BUSADDR 0x1a4
#define SCB_NEXT2 0x1a6
#define SCB_CONTROL 0x1a8
#define TARGET_SCB 0x80
#define DISCENB 0x40
......@@ -3697,7 +3684,13 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define SCB_TASK_ATTRIBUTE 0x1ab
#define SCB_BUSADDR 0x1ac
#define SCB_CDB_LEN 0x1ac
#define SCB_CDB_LEN_PTR 0x80
#define SCB_TASK_MANAGEMENT 0x1ad
#define SCB_TAG 0x1ae
#define SCB_FIFO_USE_COUNT 0x1ae
#define SCB_SPARE 0x1b0
#define SCB_PKT_LUN 0x1b0
......@@ -3775,5 +3768,5 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
/* Exported Labels */
#define LABEL_seq_isr 0x26d
#define LABEL_timer_isr 0x269
#define LABEL_seq_isr 0x270
#define LABEL_timer_isr 0x26c
......@@ -2,8 +2,8 @@
* DO NOT EDIT - This file is automatically generated
* from the following source files:
*
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#89 $
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#65 $
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#91 $
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#67 $
*/
#include "aic79xx_osm.h"
......@@ -65,13 +65,14 @@ static ahd_reg_parse_entry_t SEQINTCODE_parse_table[] = {
{ "TRACEPOINT1", 0x16, 0xff },
{ "TRACEPOINT2", 0x17, 0xff },
{ "TRACEPOINT3", 0x18, 0xff },
{ "SAW_HWERR", 0x19, 0xff }
{ "SAW_HWERR", 0x19, 0xff },
{ "BAD_SCB_STATUS", 0x1a, 0xff }
};
int
ahd_seqintcode_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(SEQINTCODE_parse_table, 26, "SEQINTCODE",
return (ahd_print_register(SEQINTCODE_parse_table, 27, "SEQINTCODE",
0x02, regvalue, cur_col, wrap));
}
......@@ -3097,18 +3098,11 @@ ahd_longjmp_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
0xf8, regvalue, cur_col, wrap));
}
int
ahd_longjmp_scb_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "LONGJMP_SCB",
0xfa, regvalue, cur_col, wrap));
}
int
ahd_accum_save_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "ACCUM_SAVE",
0xfc, regvalue, cur_col, wrap));
0xfa, regvalue, cur_col, wrap));
}
int
......@@ -3491,50 +3485,11 @@ ahd_scb_sense_busaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x18c, regvalue, cur_col, wrap));
}
int
ahd_scb_tag_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "SCB_TAG",
0x190, regvalue, cur_col, wrap));
}
static ahd_reg_parse_entry_t SCB_CDB_LEN_parse_table[] = {
{ "SCB_CDB_LEN_PTR", 0x80, 0x80 }
};
int
ahd_scb_cdb_len_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(SCB_CDB_LEN_parse_table, 1, "SCB_CDB_LEN",
0x192, regvalue, cur_col, wrap));
}
int
ahd_scb_task_management_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "SCB_TASK_MANAGEMENT",
0x193, regvalue, cur_col, wrap));
}
int
ahd_scb_next_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "SCB_NEXT",
0x194, regvalue, cur_col, wrap));
}
int
ahd_scb_next2_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "SCB_NEXT2",
0x196, regvalue, cur_col, wrap));
}
int
ahd_scb_dataptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "SCB_DATAPTR",
0x198, regvalue, cur_col, wrap));
0x190, regvalue, cur_col, wrap));
}
static ahd_reg_parse_entry_t SCB_DATACNT_parse_table[] = {
......@@ -3546,7 +3501,7 @@ int
ahd_scb_datacnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(SCB_DATACNT_parse_table, 2, "SCB_DATACNT",
0x1a0, regvalue, cur_col, wrap));
0x198, regvalue, cur_col, wrap));
}
static ahd_reg_parse_entry_t SCB_SGPTR_parse_table[] = {
......@@ -3559,9 +3514,30 @@ int
ahd_scb_sgptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(SCB_SGPTR_parse_table, 3, "SCB_SGPTR",
0x19c, regvalue, cur_col, wrap));
}
int
ahd_scb_busaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "SCB_BUSADDR",
0x1a0, regvalue, cur_col, wrap));
}
int
ahd_scb_next_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "SCB_NEXT",
0x1a4, regvalue, cur_col, wrap));
}
int
ahd_scb_next2_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "SCB_NEXT2",
0x1a6, regvalue, cur_col, wrap));
}
static ahd_reg_parse_entry_t SCB_CONTROL_parse_table[] = {
{ "SCB_TAG_TYPE", 0x03, 0x03 },
{ "DISCONNECTED", 0x04, 0x04 },
......@@ -3609,13 +3585,31 @@ ahd_scb_task_attribute_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x1ab, regvalue, cur_col, wrap));
}
static ahd_reg_parse_entry_t SCB_CDB_LEN_parse_table[] = {
{ "SCB_CDB_LEN_PTR", 0x80, 0x80 }
};
int
ahd_scb_busaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
ahd_scb_cdb_len_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "SCB_BUSADDR",
return (ahd_print_register(SCB_CDB_LEN_parse_table, 1, "SCB_CDB_LEN",
0x1ac, regvalue, cur_col, wrap));
}
int
ahd_scb_task_management_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "SCB_TASK_MANAGEMENT",
0x1ad, regvalue, cur_col, wrap));
}
int
ahd_scb_tag_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "SCB_TAG",
0x1ae, regvalue, cur_col, wrap));
}
int
ahd_scb_spare_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
......
This diff is collapsed.
......@@ -37,7 +37,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx.h#74 $
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx.h#75 $
*
* $FreeBSD$
*/
......@@ -1082,6 +1082,14 @@ struct ahc_softc {
/* PCI cacheline size. */
u_int pci_cachesize;
/*
* Count of parity errors we have seen as a target.
* We auto-disable parity error checking after seeing
* AHC_PCI_TARGET_PERR_THRESH number of errors.
*/
u_int pci_target_perr_count;
#define AHC_PCI_TARGET_PERR_THRESH 10
/* Maximum number of sequencer instructions supported. */
u_int instruction_ram_size;
......
......@@ -37,7 +37,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#124 $
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#128 $
*
* $FreeBSD$
*/
......@@ -3949,7 +3949,6 @@ ahc_free(struct ahc_softc *ahc)
{
int i;
ahc_fini_scbdata(ahc);
switch (ahc->init_level) {
default:
case 5:
......@@ -3981,6 +3980,7 @@ ahc_free(struct ahc_softc *ahc)
ahc_dma_tag_destroy(ahc, ahc->parent_dmat);
#endif
ahc_platform_free(ahc);
ahc_fini_scbdata(ahc);
for (i = 0; i < AHC_NUM_TARGETS; i++) {
struct ahc_tmode_tstate *tstate;
......@@ -5100,7 +5100,7 @@ ahc_pause_and_flushwork(struct ahc_softc *ahc)
} while (--maxloops
&& (intstat != 0xFF || (ahc->features & AHC_REMOVABLE) == 0)
&& ((intstat & INT_PEND) != 0
|| (ahc_inb(ahc, SSTAT0) & (SELDO|SELINGO))));
|| (ahc_inb(ahc, SSTAT0) & (SELDO|SELINGO)) != 0));
if (maxloops == 0) {
printf("Infinite interrupt loop, INTSTAT = %x",
ahc_inb(ahc, INTSTAT));
......
......@@ -37,7 +37,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx_inline.h#40 $
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx_inline.h#42 $
*
* $FreeBSD$
*/
......@@ -500,7 +500,7 @@ ahc_get_sense_bufaddr(struct ahc_softc *ahc, struct scb *scb)
static __inline void ahc_sync_qoutfifo(struct ahc_softc *ahc, int op);
static __inline void ahc_sync_tqinfifo(struct ahc_softc *ahc, int op);
static __inline u_int ahc_check_cmdcmpltqueues(struct ahc_softc *ahc);
static __inline void ahc_intr(struct ahc_softc *ahc);
static __inline int ahc_intr(struct ahc_softc *ahc);
static __inline void
ahc_sync_qoutfifo(struct ahc_softc *ahc, int op)
......@@ -558,7 +558,7 @@ ahc_check_cmdcmpltqueues(struct ahc_softc *ahc)
/*
* Catch an interrupt from the adapter
*/
static __inline void
static __inline int
ahc_intr(struct ahc_softc *ahc)
{
u_int intstat;
......@@ -570,7 +570,7 @@ ahc_intr(struct ahc_softc *ahc)
* so just return. This is likely just a shared
* interrupt.
*/
return;
return (0);
}
/*
* Instead of directly reading the interrupt status register,
......@@ -585,6 +585,20 @@ ahc_intr(struct ahc_softc *ahc)
intstat = ahc_inb(ahc, INTSTAT);
}
if ((intstat & INT_PEND) == 0) {
#if AHC_PCI_CONFIG > 0
if (ahc->unsolicited_ints > 500) {
ahc->unsolicited_ints = 0;
if ((ahc->chip & AHC_PCI) != 0
&& (ahc_inb(ahc, ERROR) & PCIERRSTAT) != 0)
ahc->bus_intr(ahc);
}
#endif
ahc->unsolicited_ints++;
return (0);
}
ahc->unsolicited_ints = 0;
if (intstat & CMDCMPLT) {
ahc_outb(ahc, CLRINT, CLRCMDINT);
......@@ -604,38 +618,25 @@ ahc_intr(struct ahc_softc *ahc)
#endif
}
if (intstat == 0xFF && (ahc->features & AHC_REMOVABLE) != 0)
/* Hot eject */
return;
if ((intstat & INT_PEND) == 0) {
#if AHC_PCI_CONFIG > 0
if (ahc->unsolicited_ints > 500) {
ahc->unsolicited_ints = 0;
if ((ahc->chip & AHC_PCI) != 0
&& (ahc_inb(ahc, ERROR) & PCIERRSTAT) != 0)
ahc->bus_intr(ahc);
}
#endif
ahc->unsolicited_ints++;
return;
}
ahc->unsolicited_ints = 0;
if (intstat & BRKADRINT) {
/*
* Handle statuses that may invalidate our cached
* copy of INTSTAT separately.
*/
if (intstat == 0xFF && (ahc->features & AHC_REMOVABLE) != 0) {
/* Hot eject. Do nothing */
} else if (intstat & BRKADRINT) {
ahc_handle_brkadrint(ahc);
/* Fatal error, no more interrupts to handle. */
return;
}
} else if ((intstat & (SEQINT|SCSIINT)) != 0) {
if ((intstat & (SEQINT|SCSIINT)) != 0)
ahc_pause_bug_fix(ahc);
if ((intstat & SEQINT) != 0)
ahc_handle_seqint(ahc, intstat);
if ((intstat & SEQINT) != 0)
ahc_handle_seqint(ahc, intstat);
if ((intstat & SCSIINT) != 0)
ahc_handle_scsiint(ahc, intstat);
if ((intstat & SCSIINT) != 0)
ahc_handle_scsiint(ahc, intstat);
}
return (1);
}
#endif /* _AIC7XXX_INLINE_H_ */
This diff is collapsed.
......@@ -53,7 +53,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.h#131 $
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.h#140 $
*
*/
#ifndef _AIC7XXX_LINUX_H_
......@@ -150,8 +150,8 @@ typedef Scsi_Cmnd *ahc_io_ctx_t;
#endif /* BYTE_ORDER */
/************************* Configuration Data *********************************/
extern int aic7xxx_no_probe;
extern int aic7xxx_allow_memio;
extern u_int aic7xxx_no_probe;
extern u_int aic7xxx_allow_memio;
extern int aic7xxx_detect_complete;
extern Scsi_Host_Template aic7xxx_driver_template;
......@@ -267,7 +267,7 @@ typedef struct timer_list ahc_timer_t;
/***************************** Timer Facilities *******************************/
#define ahc_timer_init init_timer
#define ahc_timer_stop del_timer
#define ahc_timer_stop del_timer_sync
typedef void ahc_linux_callback_t (u_long);
static __inline void ahc_timer_reset(ahc_timer_t *timer, int usec,
ahc_callback_t *func, void *arg);
......@@ -305,7 +305,7 @@ ahc_scb_timer_reset(struct scb *scb, u_int usec)
#define AHC_SCSI_HAS_HOST_LOCK 0
#endif
#define AIC7XXX_DRIVER_VERSION "6.2.31"
#define AIC7XXX_DRIVER_VERSION "6.2.33"
/**************************** Front End Queues ********************************/
/*
......@@ -494,7 +494,18 @@ struct ahc_linux_target {
* manner and are allocated below 4GB, the number of S/G segments is
* unrestricted.
*/
#define AHC_NSEG 128
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
/*
* We dynamically adjust the number of segments in pre-2.5 kernels to
* avoid fragmentation issues in the SCSI mid-layer's private memory
* allocator. See aic7xxx_osm.c ahc_linux_size_nseg() for details.
*/
extern u_int ahc_linux_nseg;
#define AHC_NSEG ahc_linux_nseg
#define AHC_LINUX_MIN_NSEG 64
#else
#define AHC_NSEG 128
#endif
/*
* Per-SCB OSM storage.
......@@ -538,9 +549,7 @@ struct ahc_platform_data {
TAILQ_HEAD(, ahc_linux_device) device_runq;
struct ahc_completeq completeq;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,93)
spinlock_t spin_lock;
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
struct tasklet_struct runq_tasklet;
#endif
......@@ -699,7 +708,6 @@ static __inline void ahc_list_lockinit(void);
static __inline void ahc_list_lock(unsigned long *flags);
static __inline void ahc_list_unlock(unsigned long *flags);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,93)
static __inline void
ahc_lockinit(struct ahc_softc *ahc)
{
......@@ -729,7 +737,8 @@ ahc_midlayer_entrypoint_lock(struct ahc_softc *ahc, unsigned long *flags)
* trade the io_request_lock for our per-softc lock.
*/
#if AHC_SCSI_HAS_HOST_LOCK == 0
ahc_lock(ahc, flags);
spin_unlock(&io_request_lock);
spin_lock(&ahc->platform_data->spin_lock);
#endif
}
......@@ -737,7 +746,8 @@ static __inline void
ahc_midlayer_entrypoint_unlock(struct ahc_softc *ahc, unsigned long *flags)
{
#if AHC_SCSI_HAS_HOST_LOCK == 0
ahc_unlock(ahc, flags);
spin_unlock(&ahd->platform_data->spin_lock);
spin_lock(&io_request_lock);
#endif
}
......@@ -785,65 +795,6 @@ ahc_list_unlock(unsigned long *flags)
spin_unlock_irqrestore(&ahc_list_spinlock, *flags);
}
#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,1,93) */
static __inline void
ahc_lockinit(struct ahc_softc *ahc)
{
}
static __inline void
ahc_lock(struct ahc_softc *ahc, unsigned long *flags)
{
save_flags(*flags);
cli();
}
static __inline void
ahc_unlock(struct ahc_softc *ahc, unsigned long *flags)
{
restore_flags(*flags);
}
static __inline void
ahc_done_lockinit(struct ahc_softc *ahc)
{
}
static __inline void
ahc_done_lock(struct ahc_softc *ahc, unsigned long *flags)
{
/*
* The done lock is always held while
* the ahc lock is held so blocking
* interrupts again would have no effect.
*/
}
static __inline void
ahc_done_unlock(struct ahc_softc *ahc, unsigned long *flags)
{
}
static __inline void
ahc_list_lockinit()
{
}
static __inline void
ahc_list_lock(unsigned long *flags)
{
save_flags(*flags);
cli();
}
static __inline void
ahc_list_unlock(unsigned long *flags)
{
restore_flags(*flags);
}
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) */
/******************************* PCI Definitions ******************************/
/*
* PCIM_xxx: mask to locate subfield in register
......@@ -902,16 +853,6 @@ int aic7770_map_registers(struct ahc_softc *ahc,
int aic7770_map_int(struct ahc_softc *ahc, u_int irq);
/******************************* PCI Routines *********************************/
/*
* We need to use the bios32.h routines if we are kernel version 2.1.92 or less.
*/
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,1,92)
#if defined(__sparc_v9__) || defined(__powerpc__)
#error "PPC and Sparc platforms are only supported under 2.1.92 and above"
#endif
#include <linux/bios32.h>
#endif
int ahc_linux_pci_init(void);
void ahc_linux_pci_exit(void);
int ahc_pci_map_registers(struct ahc_softc *ahc);
......@@ -1224,7 +1165,8 @@ void ahc_platform_set_tags(struct ahc_softc *ahc,
int ahc_platform_abort_scbs(struct ahc_softc *ahc, int target,
char channel, int lun, u_int tag,
role_t role, uint32_t status);
irqreturn_t ahc_linux_isr(int irq, void *dev_id, struct pt_regs * regs);
AIC_LINUX_IRQRETURN_T
ahc_linux_isr(int irq, void *dev_id, struct pt_regs * regs);
void ahc_platform_flushwork(struct ahc_softc *ahc);
int ahc_softc_comp(struct ahc_softc *, struct ahc_softc *);
void ahc_done(struct ahc_softc*, struct scb*);
......@@ -1239,5 +1181,5 @@ void ahc_platform_dump_card_state(struct ahc_softc *ahc);
#define AHC_PCI_CONFIG 0
#endif
#define bootverbose aic7xxx_verbose
extern int aic7xxx_verbose;
extern u_int aic7xxx_verbose;
#endif /* _AIC7XXX_LINUX_H_ */
......@@ -39,7 +39,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#62 $
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#63 $
*
* $FreeBSD$
*/
......@@ -837,14 +837,6 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
command = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1);
command |= PCIM_CMD_BUSMASTEREN;
/*
* Disable PCI parity error reporting. Users typically
* do this to work around broken PCI chipsets that get
* the parity timing wrong and thus generate lots of spurious
* errors.
*/
if ((ahc->flags & AHC_DISABLE_PCI_PERR) != 0)
command &= ~PCIM_CMD_PERRESPEN;
ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, /*bytes*/1);
/* On all PCI adapters, we allow SCB paging */
......@@ -854,6 +846,19 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
if (error != 0)
return (error);
/*
* Disable PCI parity error checking. Users typically
* do this to work around broken PCI chipsets that get
* the parity timing wrong and thus generate lots of spurious
* errors. The chip only allows us to disable *all* parity
* error reporting when doing this, so CIO bus, scb ram, and
* scratch ram parity errors will be ignored too.
*/
if ((ahc->flags & AHC_DISABLE_PCI_PERR) != 0) {
ahc->pause |= FAILDIS;
ahc->unpause |= FAILDIS;
}
ahc->bus_intr = ahc_pci_intr;
ahc->bus_chip_init = ahc_pci_chip_init;
ahc->bus_suspend = ahc_pci_suspend;
......@@ -1998,6 +2003,7 @@ ahc_pci_intr(struct ahc_softc *ahc)
ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8));
if (status1 & DPE) {
ahc->pci_target_perr_count++;
printf("%s: Data Parity Error Detected during address "
"or write data phase\n", ahc_name(ahc));
}
......@@ -2029,6 +2035,19 @@ ahc_pci_intr(struct ahc_softc *ahc)
ahc_outb(ahc, CLRINT, CLRPARERR);
}
if (ahc->pci_target_perr_count > AHC_PCI_TARGET_PERR_THRESH) {
printf(
"%s: WARNING WARNING WARNING WARNING\n"
"%s: Too many PCI parity errors observed as a target.\n"
"%s: Some device on this bus is generating bad parity.\n"
"%s: This is an error *observed by*, not *generated by*, this controller.\n"
"%s: PCI parity error checking has been disabled.\n"
"%s: WARNING WARNING WARNING WARNING\n",
ahc_name(ahc), ahc_name(ahc), ahc_name(ahc),
ahc_name(ahc), ahc_name(ahc), ahc_name(ahc));
ahc->pause |= FAILDIS;
ahc->unpause |= FAILDIS;
}
ahc_unpause(ahc);
}
......
......@@ -37,7 +37,7 @@
* String handling code courtesy of Gerard Roudier's <groudier@club-internet.fr>
* sym driver.
*
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_proc.c#24 $
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_proc.c#27 $
*/
#include "aic7xxx_osm.h"
#include "aic7xxx_inline.h"
......@@ -148,8 +148,9 @@ ahc_dump_target_state(struct ahc_softc *ahc, struct info_str *info,
tinfo = ahc_fetch_transinfo(ahc, channel, our_id,
target_id, &tstate);
copy_info(info, "Channel %c Target %d Negotiation Settings\n",
channel, target_id);
if ((ahc->features & AHC_TWIN) != 0)
copy_info(info, "Channel %c ", channel);
copy_info(info, "Target %d Negotiation Settings\n", target_id);
copy_info(info, "\tUser: ");
ahc_format_transinfo(info, &tinfo->user);
targ = ahc->platform_data->targets[target_offset];
......@@ -327,7 +328,10 @@ ahc_linux_proc_info(char *buffer, char **start, off_t offset,
AIC7XXX_DRIVER_VERSION);
copy_info(&info, "%s\n", ahc->description);
ahc_controller_info(ahc, ahc_info);
copy_info(&info, "%s\n\n", ahc_info);
copy_info(&info, "%s\n", ahc_info);
copy_info(&info, "Allocated SCBs: %d, SG List Length: %d\n\n",
ahc->scb_data->numscbs, AHC_NSEG);
if (ahc->seep_config == NULL)
copy_info(&info, "No Serial EEPROM\n");
......
......@@ -1335,7 +1335,7 @@ aic_error_action(struct scsi_cmnd *cmd, struct scsi_inquiry_data *inq_data,
char *
aic_parse_brace_option(char *opt_name, char *opt_arg, char *end, int depth,
aic_option_callback_t *callback, void *callback_arg)
aic_option_callback_t *callback, u_long callback_arg)
{
char *tok_end;
char *tok_end2;
......
......@@ -15,15 +15,58 @@
* Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
*
* $FreeBSD: src/sys/cam/scsi/scsi_all.h,v 1.21 2002/10/08 17:12:44 ken Exp $
*
* Copyright (c) 2003 Adaptec Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* $Id$
*/
#ifndef _AICLIB_H
#define _AICLIB_H
/*
* SCSI general interface description
* Linux Interrupt Support.
*/
#ifndef _SCSI_SCSI_ALL_H
#define _SCSI_SCSI_ALL_H 1
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
#define AIC_LINUX_IRQRETURN_T irqreturn_t
#define AIC_LINUX_IRQRETURN(ours) return (IRQ_RETVAL(ours))
#else
#define AIC_LINUX_IRQRETURN_T void
#define AIC_LINUX_IRQRETURN(ours) return
#endif
/*
* SCSI command format
......@@ -906,10 +949,10 @@ int aic_inquiry_match(caddr_t /*inqbuffer*/,
int aic_static_inquiry_match(caddr_t /*inqbuffer*/,
caddr_t /*table_entry*/);
typedef void aic_option_callback_t(void *, int, int, int32_t);
typedef void aic_option_callback_t(u_long, int, int, int32_t);
char * aic_parse_brace_option(char *opt_name, char *opt_arg,
char *end, int depth,
aic_option_callback_t *, void *);
aic_option_callback_t *, u_long);
static __inline void scsi_extract_sense(struct scsi_sense_data *sense,
int *error_code, int *sense_key,
......@@ -1003,4 +1046,4 @@ scsi_4btoul(uint8_t *bytes)
return (rv);
}
#endif /*_SCSI_SCSI_ALL_H*/
#endif /*_AICLIB_H */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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