1
0
Fork 0

Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (40 commits)
  [SCSI] jazz_esp, sgiwd93, sni_53c710, sun3x_esp: fix platform driver hotplug/coldplug
  [SCSI] aic7xxx: add const
  [SCSI] aic7xxx: add static
  [SCSI] aic7xxx: Update _shipped files
  [SCSI] aic7xxx: teach aicasm to not emit unused debug code/data
  [SCSI] qla2xxx: Update version number to 8.02.01-k2.
  [SCSI] qla2xxx: Correct regression in relogin code.
  [SCSI] qla2xxx: Correct misc. endian and byte-ordering issues.
  [SCSI] qla2xxx: make qla2x00_issue_iocb_timeout() static
  [SCSI] qla2xxx: qla_os.c, make 2 functions static
  [SCSI] qla2xxx: Re-register FDMI information after a LIP.
  [SCSI] qla2xxx: Correct SRB usage-after-completion/free issues.
  [SCSI] qla2xxx: Correct ISP84XX verify-chip response handling.
  [SCSI] qla2xxx: Wakeup DPC thread to process any deferred-work requests.
  [SCSI] qla2xxx: Collapse RISC-RAM retrieval code during a firmware-dump.
  [SCSI] m68k: new mac_esp scsi driver
  [SCSI] zfcp: Add some statistics provided by the FCP adapter to the sysfs
  [SCSI] zfcp: Print some messages only during ERP
  [SCSI] zfcp: Wait for free SBAL during exchange config
  [SCSI] scsi_transport_fc: fc_user_scan correction
  ...
hifive-unleashed-5.1
Linus Torvalds 2008-04-27 11:25:00 -07:00
commit 064922a805
74 changed files with 4057 additions and 5142 deletions

View File

@ -699,14 +699,26 @@ static struct bsg_device *bsg_alloc_device(void)
return bd;
}
static void bsg_kref_release_function(struct kref *kref)
{
struct bsg_class_device *bcd =
container_of(kref, struct bsg_class_device, ref);
if (bcd->release)
bcd->release(bcd->parent);
put_device(bcd->parent);
}
static int bsg_put_device(struct bsg_device *bd)
{
int ret = 0;
struct device *dev = bd->queue->bsg_dev.dev;
int ret = 0, do_free;
struct request_queue *q = bd->queue;
mutex_lock(&bsg_mutex);
if (!atomic_dec_and_test(&bd->ref_count))
do_free = atomic_dec_and_test(&bd->ref_count);
if (!do_free)
goto out;
dprintk("%s: tearing down\n", bd->name);
@ -723,12 +735,13 @@ static int bsg_put_device(struct bsg_device *bd)
*/
ret = bsg_complete_all_commands(bd);
blk_put_queue(bd->queue);
hlist_del(&bd->dev_list);
kfree(bd);
out:
mutex_unlock(&bsg_mutex);
put_device(dev);
kref_put(&q->bsg_dev.ref, bsg_kref_release_function);
if (do_free)
blk_put_queue(q);
return ret;
}
@ -796,7 +809,7 @@ static struct bsg_device *bsg_get_device(struct inode *inode, struct file *file)
mutex_lock(&bsg_mutex);
bcd = idr_find(&bsg_minor_idr, iminor(inode));
if (bcd)
get_device(bcd->dev);
kref_get(&bcd->ref);
mutex_unlock(&bsg_mutex);
if (!bcd)
@ -808,7 +821,7 @@ static struct bsg_device *bsg_get_device(struct inode *inode, struct file *file)
bd = bsg_add_device(inode, bcd->queue, file);
if (IS_ERR(bd))
put_device(bcd->dev);
kref_put(&bcd->ref, bsg_kref_release_function);
return bd;
}
@ -947,14 +960,14 @@ void bsg_unregister_queue(struct request_queue *q)
idr_remove(&bsg_minor_idr, bcd->minor);
sysfs_remove_link(&q->kobj, "bsg");
device_unregister(bcd->class_dev);
put_device(bcd->dev);
bcd->class_dev = NULL;
kref_put(&bcd->ref, bsg_kref_release_function);
mutex_unlock(&bsg_mutex);
}
EXPORT_SYMBOL_GPL(bsg_unregister_queue);
int bsg_register_queue(struct request_queue *q, struct device *gdev,
const char *name)
int bsg_register_queue(struct request_queue *q, struct device *parent,
const char *name, void (*release)(struct device *))
{
struct bsg_class_device *bcd;
dev_t dev;
@ -965,7 +978,7 @@ int bsg_register_queue(struct request_queue *q, struct device *gdev,
if (name)
devname = name;
else
devname = gdev->bus_id;
devname = parent->bus_id;
/*
* we need a proper transport to send commands, not a stacked device
@ -996,9 +1009,11 @@ int bsg_register_queue(struct request_queue *q, struct device *gdev,
bcd->minor = minor;
bcd->queue = q;
bcd->dev = get_device(gdev);
bcd->parent = get_device(parent);
bcd->release = release;
kref_init(&bcd->ref);
dev = MKDEV(bsg_major, bcd->minor);
class_dev = device_create(bsg_class, gdev, dev, "%s", devname);
class_dev = device_create(bsg_class, parent, dev, "%s", devname);
if (IS_ERR(class_dev)) {
ret = PTR_ERR(class_dev);
goto put_dev;
@ -1017,7 +1032,7 @@ int bsg_register_queue(struct request_queue *q, struct device *gdev,
unregister_class_dev:
device_unregister(class_dev);
put_dev:
put_device(gdev);
put_device(parent);
remove_idr:
idr_remove(&bsg_minor_idr, minor);
unlock:

View File

@ -31,7 +31,6 @@
static LIST_HEAD(container_list);
static DEFINE_MUTEX(container_list_lock);
static struct class enclosure_class;
static struct class enclosure_component_class;
/**
* enclosure_find - find an enclosure given a device
@ -166,6 +165,40 @@ void enclosure_unregister(struct enclosure_device *edev)
}
EXPORT_SYMBOL_GPL(enclosure_unregister);
#define ENCLOSURE_NAME_SIZE 64
static void enclosure_link_name(struct enclosure_component *cdev, char *name)
{
strcpy(name, "enclosure_device:");
strcat(name, cdev->cdev.bus_id);
}
static void enclosure_remove_links(struct enclosure_component *cdev)
{
char name[ENCLOSURE_NAME_SIZE];
enclosure_link_name(cdev, name);
sysfs_remove_link(&cdev->dev->kobj, name);
sysfs_remove_link(&cdev->cdev.kobj, "device");
}
static int enclosure_add_links(struct enclosure_component *cdev)
{
int error;
char name[ENCLOSURE_NAME_SIZE];
error = sysfs_create_link(&cdev->cdev.kobj, &cdev->dev->kobj, "device");
if (error)
return error;
enclosure_link_name(cdev, name);
error = sysfs_create_link(&cdev->dev->kobj, &cdev->cdev.kobj, name);
if (error)
sysfs_remove_link(&cdev->cdev.kobj, "device");
return error;
}
static void enclosure_release(struct device *cdev)
{
struct enclosure_device *edev = to_enclosure_device(cdev);
@ -178,10 +211,15 @@ static void enclosure_component_release(struct device *dev)
{
struct enclosure_component *cdev = to_enclosure_component(dev);
put_device(cdev->dev);
if (cdev->dev) {
enclosure_remove_links(cdev);
put_device(cdev->dev);
}
put_device(dev->parent);
}
static struct attribute_group *enclosure_groups[];
/**
* enclosure_component_register - add a particular component to an enclosure
* @edev: the enclosure to add the component
@ -217,12 +255,14 @@ enclosure_component_register(struct enclosure_device *edev,
ecomp->number = number;
cdev = &ecomp->cdev;
cdev->parent = get_device(&edev->edev);
cdev->class = &enclosure_component_class;
if (name)
snprintf(cdev->bus_id, BUS_ID_SIZE, "%s", name);
else
snprintf(cdev->bus_id, BUS_ID_SIZE, "%u", number);
cdev->release = enclosure_component_release;
cdev->groups = enclosure_groups;
err = device_register(cdev);
if (err)
ERR_PTR(err);
@ -255,10 +295,12 @@ int enclosure_add_device(struct enclosure_device *edev, int component,
cdev = &edev->component[component];
device_del(&cdev->cdev);
if (cdev->dev)
enclosure_remove_links(cdev);
put_device(cdev->dev);
cdev->dev = get_device(dev);
return device_add(&cdev->cdev);
return enclosure_add_links(cdev);
}
EXPORT_SYMBOL_GPL(enclosure_add_device);
@ -442,24 +484,32 @@ static ssize_t get_component_type(struct device *cdev,
}
static struct device_attribute enclosure_component_attrs[] = {
__ATTR(fault, S_IRUGO | S_IWUSR, get_component_fault,
set_component_fault),
__ATTR(status, S_IRUGO | S_IWUSR, get_component_status,
set_component_status),
__ATTR(active, S_IRUGO | S_IWUSR, get_component_active,
set_component_active),
__ATTR(locate, S_IRUGO | S_IWUSR, get_component_locate,
set_component_locate),
__ATTR(type, S_IRUGO, get_component_type, NULL),
__ATTR_NULL
static DEVICE_ATTR(fault, S_IRUGO | S_IWUSR, get_component_fault,
set_component_fault);
static DEVICE_ATTR(status, S_IRUGO | S_IWUSR, get_component_status,
set_component_status);
static DEVICE_ATTR(active, S_IRUGO | S_IWUSR, get_component_active,
set_component_active);
static DEVICE_ATTR(locate, S_IRUGO | S_IWUSR, get_component_locate,
set_component_locate);
static DEVICE_ATTR(type, S_IRUGO, get_component_type, NULL);
static struct attribute *enclosure_component_attrs[] = {
&dev_attr_fault.attr,
&dev_attr_status.attr,
&dev_attr_active.attr,
&dev_attr_locate.attr,
&dev_attr_type.attr,
NULL
};
static struct class enclosure_component_class = {
.name = "enclosure_component",
.owner = THIS_MODULE,
.dev_attrs = enclosure_component_attrs,
.dev_release = enclosure_component_release,
static struct attribute_group enclosure_group = {
.attrs = enclosure_component_attrs,
};
static struct attribute_group *enclosure_groups[] = {
&enclosure_group,
NULL
};
static int __init enclosure_init(void)
@ -469,20 +519,12 @@ static int __init enclosure_init(void)
err = class_register(&enclosure_class);
if (err)
return err;
err = class_register(&enclosure_component_class);
if (err)
goto err_out;
return 0;
err_out:
class_unregister(&enclosure_class);
return err;
}
static void __exit enclosure_exit(void)
{
class_unregister(&enclosure_component_class);
class_unregister(&enclosure_class);
}

View File

@ -1927,7 +1927,8 @@ zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *adapter,
/* setup new FSF request */
retval = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_CONFIG_DATA,
0, NULL, &lock_flags, &fsf_req);
ZFCP_WAIT_FOR_SBAL, NULL, &lock_flags,
&fsf_req);
if (retval) {
ZFCP_LOG_INFO("error: Could not create exchange configuration "
"data request for adapter %s.\n",
@ -2035,21 +2036,21 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
min(FC_SERIAL_NUMBER_SIZE, 17));
}
ZFCP_LOG_NORMAL("The adapter %s reported the following "
"characteristics:\n"
"WWNN 0x%016Lx, "
"WWPN 0x%016Lx, "
"S_ID 0x%06x,\n"
"adapter version 0x%x, "
"LIC version 0x%x, "
"FC link speed %d Gb/s\n",
zfcp_get_busid_by_adapter(adapter),
(wwn_t) fc_host_node_name(shost),
(wwn_t) fc_host_port_name(shost),
fc_host_port_id(shost),
adapter->hydra_version,
adapter->fsf_lic_version,
fc_host_speed(shost));
if (fsf_req->erp_action)
ZFCP_LOG_NORMAL("The adapter %s reported the following "
"characteristics:\n"
"WWNN 0x%016Lx, WWPN 0x%016Lx, "
"S_ID 0x%06x,\n"
"adapter version 0x%x, "
"LIC version 0x%x, "
"FC link speed %d Gb/s\n",
zfcp_get_busid_by_adapter(adapter),
(wwn_t) fc_host_node_name(shost),
(wwn_t) fc_host_port_name(shost),
fc_host_port_id(shost),
adapter->hydra_version,
adapter->fsf_lic_version,
fc_host_speed(shost));
if (ZFCP_QTCB_VERSION < bottom->low_qtcb_version) {
ZFCP_LOG_NORMAL("error: the adapter %s "
"only supports newer control block "
@ -2114,8 +2115,10 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
zfcp_erp_adapter_shutdown(adapter, 0, 127, fsf_req);
return -EIO;
case FC_PORTTYPE_NPORT:
ZFCP_LOG_NORMAL("Switched fabric fibrechannel "
"network detected at adapter %s.\n",
if (fsf_req->erp_action)
ZFCP_LOG_NORMAL("Switched fabric fibrechannel "
"network detected at adapter "
"%s.\n",
zfcp_get_busid_by_adapter(adapter));
break;
default:

View File

@ -213,6 +213,7 @@
#define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010
#define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020
#define FSF_FEATURE_UPDATE_ALERT 0x00000100
#define FSF_FEATURE_MEASUREMENT_DATA 0x00000200
/* host connection features */
#define FSF_FEATURE_NPIV_MODE 0x00000001
@ -340,6 +341,15 @@ struct fsf_qtcb_prefix {
u8 res1[20];
} __attribute__ ((packed));
struct fsf_statistics_info {
u64 input_req;
u64 output_req;
u64 control_req;
u64 input_mb;
u64 output_mb;
u64 seconds_act;
} __attribute__ ((packed));
union fsf_status_qual {
u8 byte[FSF_STATUS_QUALIFIER_SIZE];
u16 halfword[FSF_STATUS_QUALIFIER_SIZE / sizeof (u16)];
@ -436,7 +446,8 @@ struct fsf_qtcb_bottom_config {
u32 hardware_version;
u8 serial_number[32];
struct fsf_nport_serv_param plogi_payload;
u8 res4[160];
struct fsf_statistics_info stat_info;
u8 res4[112];
} __attribute__ ((packed));
struct fsf_qtcb_bottom_port {
@ -469,7 +480,10 @@ struct fsf_qtcb_bottom_port {
u64 control_requests;
u64 input_mb; /* where 1 MByte == 1.000.000 Bytes */
u64 output_mb; /* where 1 MByte == 1.000.000 Bytes */
u8 res2[256];
u8 cp_util;
u8 cb_util;
u8 a_util;
u8 res2[253];
} __attribute__ ((packed));
union fsf_qtcb_bottom {

View File

@ -40,6 +40,7 @@ static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int,
unsigned int, unsigned int);
static struct device_attribute *zfcp_sysfs_sdev_attrs[];
static struct device_attribute *zfcp_a_stats_attrs[];
struct zfcp_data zfcp_data = {
.scsi_host_template = {
@ -61,6 +62,7 @@ struct zfcp_data zfcp_data = {
.use_clustering = 1,
.sdev_attrs = zfcp_sysfs_sdev_attrs,
.max_sectors = ZFCP_MAX_SECTORS,
.shost_attrs = zfcp_a_stats_attrs,
},
.driver_version = ZFCP_VERSION,
};
@ -809,4 +811,116 @@ static struct device_attribute *zfcp_sysfs_sdev_attrs[] = {
NULL
};
static ssize_t zfcp_sysfs_adapter_util_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct Scsi_Host *scsi_host = dev_to_shost(dev);
struct fsf_qtcb_bottom_port *qtcb_port;
int retval;
struct zfcp_adapter *adapter;
adapter = (struct zfcp_adapter *) scsi_host->hostdata[0];
if (!(adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA))
return -EOPNOTSUPP;
qtcb_port = kzalloc(sizeof(struct fsf_qtcb_bottom_port), GFP_KERNEL);
if (!qtcb_port)
return -ENOMEM;
retval = zfcp_fsf_exchange_port_data_sync(adapter, qtcb_port);
if (!retval)
retval = sprintf(buf, "%u %u %u\n", qtcb_port->cp_util,
qtcb_port->cb_util, qtcb_port->a_util);
kfree(qtcb_port);
return retval;
}
static int zfcp_sysfs_adapter_ex_config(struct device *dev,
struct fsf_statistics_info *stat_inf)
{
int retval;
struct fsf_qtcb_bottom_config *qtcb_config;
struct Scsi_Host *scsi_host = dev_to_shost(dev);
struct zfcp_adapter *adapter;
adapter = (struct zfcp_adapter *) scsi_host->hostdata[0];
if (!(adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA))
return -EOPNOTSUPP;
qtcb_config = kzalloc(sizeof(struct fsf_qtcb_bottom_config),
GFP_KERNEL);
if (!qtcb_config)
return -ENOMEM;
retval = zfcp_fsf_exchange_config_data_sync(adapter, qtcb_config);
if (!retval)
*stat_inf = qtcb_config->stat_info;
kfree(qtcb_config);
return retval;
}
static ssize_t zfcp_sysfs_adapter_request_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct fsf_statistics_info stat_info;
int retval;
retval = zfcp_sysfs_adapter_ex_config(dev, &stat_info);
if (retval)
return retval;
return sprintf(buf, "%llu %llu %llu\n",
(unsigned long long) stat_info.input_req,
(unsigned long long) stat_info.output_req,
(unsigned long long) stat_info.control_req);
}
static ssize_t zfcp_sysfs_adapter_mb_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct fsf_statistics_info stat_info;
int retval;
retval = zfcp_sysfs_adapter_ex_config(dev, &stat_info);
if (retval)
return retval;
return sprintf(buf, "%llu %llu\n",
(unsigned long long) stat_info.input_mb,
(unsigned long long) stat_info.output_mb);
}
static ssize_t zfcp_sysfs_adapter_sec_active_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct fsf_statistics_info stat_info;
int retval;
retval = zfcp_sysfs_adapter_ex_config(dev, &stat_info);
if (retval)
return retval;
return sprintf(buf, "%llu\n",
(unsigned long long) stat_info.seconds_act);
}
static DEVICE_ATTR(utilization, S_IRUGO, zfcp_sysfs_adapter_util_show, NULL);
static DEVICE_ATTR(requests, S_IRUGO, zfcp_sysfs_adapter_request_show, NULL);
static DEVICE_ATTR(megabytes, S_IRUGO, zfcp_sysfs_adapter_mb_show, NULL);
static DEVICE_ATTR(seconds_active, S_IRUGO,
zfcp_sysfs_adapter_sec_active_show, NULL);
static struct device_attribute *zfcp_a_stats_attrs[] = {
&dev_attr_utilization,
&dev_attr_requests,
&dev_attr_megabytes,
&dev_attr_seconds_active,
NULL
};
#undef ZFCP_LOG_AREA

View File

@ -1499,7 +1499,7 @@ static void FlashPoint_StartCCB(unsigned long pCurrCard, struct sccb *p_Sccb)
thisCard = ((struct sccb_card *)pCurrCard)->cardIndex;
ioport = ((struct sccb_card *)pCurrCard)->ioPort;
if ((p_Sccb->TargID > MAX_SCSI_TAR) || (p_Sccb->Lun > MAX_LUN)) {
if ((p_Sccb->TargID >= MAX_SCSI_TAR) || (p_Sccb->Lun >= MAX_LUN)) {
p_Sccb->HostStatus = SCCB_COMPLETE;
p_Sccb->SccbStatus = SCCB_ERROR;

View File

@ -1677,6 +1677,16 @@ config MAC_SCSI
SCSI-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
config SCSI_MAC_ESP
tristate "Macintosh NCR53c9[46] SCSI"
depends on MAC && SCSI
help
This is the NCR 53c9x SCSI controller found on most of the 68040
based Macintoshes.
To compile this driver as a module, choose M here: the module
will be called mac_esp.
config MVME147_SCSI
bool "WD33C93 SCSI driver for MVME147"
depends on MVME147 && SCSI=y

View File

@ -46,6 +46,7 @@ obj-$(CONFIG_MVME147_SCSI) += mvme147.o wd33c93.o
obj-$(CONFIG_SGIWD93_SCSI) += sgiwd93.o wd33c93.o
obj-$(CONFIG_ATARI_SCSI) += atari_scsi.o
obj-$(CONFIG_MAC_SCSI) += mac_scsi.o
obj-$(CONFIG_SCSI_MAC_ESP) += esp_scsi.o mac_esp.o
obj-$(CONFIG_SUN3_SCSI) += sun3_scsi.o sun3_scsi_vme.o
obj-$(CONFIG_MVME16x_SCSI) += 53c700.o mvme16x_scsi.o
obj-$(CONFIG_BVME6000_SCSI) += 53c700.o bvme6000_scsi.o

View File

@ -1432,15 +1432,10 @@ static void run(struct work_struct *work)
*/
static irqreturn_t intr(int irqno, void *dev_id)
{
struct Scsi_Host *shpnt = (struct Scsi_Host *)dev_id;
struct Scsi_Host *shpnt = dev_id;
unsigned long flags;
unsigned char rev, dmacntrl0;
if (!shpnt) {
printk(KERN_ERR "aha152x: catched interrupt %d for unknown controller.\n", irqno);
return IRQ_NONE;
}
/*
* Read a couple of registers that are known to not be all 1's. If
* we read all 1's (-1), that means that either:

View File

@ -153,8 +153,6 @@ struct aha1542_hostdata {
#define HOSTDATA(host) ((struct aha1542_hostdata *) &host->hostdata)
static struct Scsi_Host *aha_host[7]; /* One for each IRQ level (9-15) */
static DEFINE_SPINLOCK(aha1542_lock);
@ -163,8 +161,7 @@ static DEFINE_SPINLOCK(aha1542_lock);
static void setup_mailboxes(int base_io, struct Scsi_Host *shpnt);
static int aha1542_restart(struct Scsi_Host *shost);
static void aha1542_intr_handle(struct Scsi_Host *shost, void *dev_id);
static irqreturn_t do_aha1542_intr_handle(int irq, void *dev_id);
static void aha1542_intr_handle(struct Scsi_Host *shost);
#define aha1542_intr_reset(base) outb(IRST, CONTROL(base))
@ -404,23 +401,19 @@ fail:
}
/* A quick wrapper for do_aha1542_intr_handle to grab the spin lock */
static irqreturn_t do_aha1542_intr_handle(int irq, void *dev_id)
static irqreturn_t do_aha1542_intr_handle(int dummy, void *dev_id)
{
unsigned long flags;
struct Scsi_Host *shost;
shost = aha_host[irq - 9];
if (!shost)
panic("Splunge!");
struct Scsi_Host *shost = dev_id;
spin_lock_irqsave(shost->host_lock, flags);
aha1542_intr_handle(shost, dev_id);
aha1542_intr_handle(shost);
spin_unlock_irqrestore(shost->host_lock, flags);
return IRQ_HANDLED;
}
/* A "high" level interrupt handler */
static void aha1542_intr_handle(struct Scsi_Host *shost, void *dev_id)
static void aha1542_intr_handle(struct Scsi_Host *shost)
{
void (*my_done) (Scsi_Cmnd *) = NULL;
int errstatus, mbi, mbo, mbistatus;
@ -1197,7 +1190,8 @@ fail:
DEB(printk("aha1542_detect: enable interrupt channel %d\n", irq_level));
spin_lock_irqsave(&aha1542_lock, flags);
if (request_irq(irq_level, do_aha1542_intr_handle, 0, "aha1542", NULL)) {
if (request_irq(irq_level, do_aha1542_intr_handle, 0,
"aha1542", shpnt)) {
printk(KERN_ERR "Unable to allocate IRQ for adaptec controller.\n");
spin_unlock_irqrestore(&aha1542_lock, flags);
goto unregister;
@ -1205,7 +1199,7 @@ fail:
if (dma_chan != 0xFF) {
if (request_dma(dma_chan, "aha1542")) {
printk(KERN_ERR "Unable to allocate DMA channel for Adaptec.\n");
free_irq(irq_level, NULL);
free_irq(irq_level, shpnt);
spin_unlock_irqrestore(&aha1542_lock, flags);
goto unregister;
}
@ -1214,7 +1208,7 @@ fail:
enable_dma(dma_chan);
}
}
aha_host[irq_level - 9] = shpnt;
shpnt->this_id = scsi_id;
shpnt->unique_id = base_io;
shpnt->io_port = base_io;
@ -1276,7 +1270,7 @@ unregister:
static int aha1542_release(struct Scsi_Host *shost)
{
if (shost->irq)
free_irq(shost->irq, NULL);
free_irq(shost->irq, shost);
if (shost->dma_channel != 0xff)
free_dma(shost->dma_channel);
if (shost->io_port && shost->n_io_port)

View File

@ -815,7 +815,7 @@ struct ahd_tmode_tstate {
struct ahd_phase_table_entry {
uint8_t phase;
uint8_t mesg_out; /* Message response to parity errors */
char *phasemsg;
const char *phasemsg;
};
/************************** Serial EEPROM Format ******************************/
@ -1314,7 +1314,7 @@ typedef int (ahd_device_setup_t)(struct ahd_softc *);
struct ahd_pci_identity {
uint64_t full_id;
uint64_t id_mask;
char *name;
const char *name;
ahd_device_setup_t *setup;
};
@ -1322,7 +1322,7 @@ struct ahd_pci_identity {
struct aic7770_identity {
uint32_t full_id;
uint32_t id_mask;
char *name;
const char *name;
ahd_device_setup_t *setup;
};
extern struct aic7770_identity aic7770_ident_table [];
@ -1333,12 +1333,11 @@ extern const int ahd_num_aic7770_devs;
/*************************** Function Declarations ****************************/
/******************************************************************************/
void ahd_reset_cmds_pending(struct ahd_softc *ahd);
/***************************** PCI Front End *********************************/
struct ahd_pci_identity *ahd_find_pci_device(ahd_dev_softc_t);
const struct ahd_pci_identity *ahd_find_pci_device(ahd_dev_softc_t);
int ahd_pci_config(struct ahd_softc *,
struct ahd_pci_identity *);
const struct ahd_pci_identity *);
int ahd_pci_test_register_access(struct ahd_softc *);
#ifdef CONFIG_PM
void ahd_pci_suspend(struct ahd_softc *);
@ -1376,16 +1375,6 @@ int ahd_write_flexport(struct ahd_softc *ahd,
int ahd_read_flexport(struct ahd_softc *ahd, u_int addr,
uint8_t *value);
/*************************** Interrupt Services *******************************/
void ahd_run_qoutfifo(struct ahd_softc *ahd);
#ifdef AHD_TARGET_MODE
void ahd_run_tqinfifo(struct ahd_softc *ahd, int paused);
#endif
void ahd_handle_hwerrint(struct ahd_softc *ahd);
void ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat);
void ahd_handle_scsiint(struct ahd_softc *ahd,
u_int intstat);
/***************************** Error Recovery *********************************/
typedef enum {
SEARCH_COMPLETE,
@ -1479,7 +1468,7 @@ extern uint32_t ahd_debug;
void ahd_print_devinfo(struct ahd_softc *ahd,
struct ahd_devinfo *devinfo);
void ahd_dump_card_state(struct ahd_softc *ahd);
int ahd_print_register(ahd_reg_parse_entry_t *table,
int ahd_print_register(const ahd_reg_parse_entry_t *table,
u_int num_entries,
const char *name,
u_int address,

View File

@ -198,6 +198,7 @@ register SEQINTCODE {
register CLRINT {
address 0x003
access_mode WO
count 19
field CLRHWERRINT 0x80 /* Rev B or greater */
field CLRBRKADRINT 0x40
field CLRSWTMINT 0x20
@ -245,6 +246,7 @@ register CLRERR {
register HCNTRL {
address 0x005
access_mode RW
count 12
field SEQ_RESET 0x80 /* Rev B or greater */
field POWRDN 0x40
field SWINT 0x10
@ -262,6 +264,7 @@ register HNSCB_QOFF {
address 0x006
access_mode RW
size 2
count 2
}
/*
@ -270,6 +273,7 @@ register HNSCB_QOFF {
register HESCB_QOFF {
address 0x008
access_mode RW
count 2
}
/*
@ -287,6 +291,7 @@ register HS_MAILBOX {
*/
register SEQINTSTAT {
address 0x00C
count 1
access_mode RO
field SEQ_SWTMRTO 0x10
field SEQ_SEQINT 0x08
@ -332,6 +337,7 @@ register SNSCB_QOFF {
*/
register SESCB_QOFF {
address 0x012
count 2
access_mode RW
modes M_CCHAN
}
@ -397,6 +403,7 @@ register DFCNTRL {
address 0x019
access_mode RW
modes M_DFF0, M_DFF1
count 11
field PRELOADEN 0x80
field SCSIENWRDIS 0x40 /* Rev B only. */
field SCSIEN 0x20
@ -415,6 +422,7 @@ register DFCNTRL {
*/
register DSCOMMAND0 {
address 0x019
count 1
access_mode RW
modes M_CFG
field CACHETHEN 0x80 /* Cache Threshold enable */
@ -580,6 +588,7 @@ register DFF_THRSH {
address 0x088
access_mode RW
modes M_CFG
count 1
field WR_DFTHRSH 0x70 {
WR_DFTHRSH_MIN,
WR_DFTHRSH_25,
@ -800,6 +809,7 @@ register PCIXCTL {
address 0x093
access_mode RW
modes M_CFG
count 1
field SERRPULSE 0x80
field UNEXPSCIEN 0x20
field SPLTSMADIS 0x10
@ -844,6 +854,7 @@ register DCHSPLTSTAT0 {
address 0x096
access_mode RW
modes M_DFF0, M_DFF1
count 2
field STAETERM 0x80
field SCBCERR 0x40
field SCADERR 0x20
@ -895,6 +906,7 @@ register DCHSPLTSTAT1 {
address 0x097
access_mode RW
modes M_DFF0, M_DFF1
count 2
field RXDATABUCKET 0x01
}
@ -1048,6 +1060,7 @@ register SGSPLTSTAT0 {
address 0x09E
access_mode RW
modes M_DFF0, M_DFF1
count 2
field STAETERM 0x80
field SCBCERR 0x40
field SCADERR 0x20
@ -1065,6 +1078,7 @@ register SGSPLTSTAT1 {
address 0x09F
access_mode RW
modes M_DFF0, M_DFF1
count 2
field RXDATABUCKET 0x01
}
@ -1086,6 +1100,7 @@ register DF0PCISTAT {
address 0x0A0
access_mode RW
modes M_CFG
count 1
field DPE 0x80
field SSE 0x40
field RMA 0x20
@ -1184,6 +1199,7 @@ register TARGPCISTAT {
address 0x0A7
access_mode RW
modes M_CFG
count 5
field DPE 0x80
field SSE 0x40
field STA 0x08
@ -1198,6 +1214,7 @@ register LQIN {
address 0x020
access_mode RW
size 20
count 2
modes M_DFF0, M_DFF1, M_SCSI
}
@ -1229,6 +1246,7 @@ register LUNPTR {
address 0x022
access_mode RW
modes M_CFG
count 2
}
/*
@ -1259,6 +1277,7 @@ register CMDLENPTR {
address 0x025
access_mode RW
modes M_CFG
count 1
}
/*
@ -1270,6 +1289,7 @@ register ATTRPTR {
address 0x026
access_mode RW
modes M_CFG
count 1
}
/*
@ -1281,6 +1301,7 @@ register FLAGPTR {
address 0x027
access_mode RW
modes M_CFG
count 1
}
/*
@ -1291,6 +1312,7 @@ register CMDPTR {
address 0x028
access_mode RW
modes M_CFG
count 1
}
/*
@ -1301,6 +1323,7 @@ register QNEXTPTR {
address 0x029
access_mode RW
modes M_CFG
count 1
}
/*
@ -1323,6 +1346,7 @@ register ABRTBYTEPTR {
address 0x02B
access_mode RW
modes M_CFG
count 1
}
/*
@ -1333,6 +1357,7 @@ register ABRTBITPTR {
address 0x02C
access_mode RW
modes M_CFG
count 1
}
/*
@ -1370,6 +1395,7 @@ register LUNLEN {
address 0x030
access_mode RW
modes M_CFG
count 2
mask ILUNLEN 0x0F
mask TLUNLEN 0xF0
}
@ -1383,6 +1409,7 @@ register CDBLIMIT {
address 0x031
access_mode RW
modes M_CFG
count 1
}
/*
@ -1394,6 +1421,7 @@ register MAXCMD {
address 0x032
access_mode RW
modes M_CFG
count 9
}
/*
@ -1458,6 +1486,7 @@ register LQCTL1 {
address 0x038
access_mode RW
modes M_DFF0, M_DFF1, M_SCSI
count 2
field PCI2PCI 0x04
field SINGLECMD 0x02
field ABORTPENDING 0x01
@ -1470,6 +1499,7 @@ register LQCTL2 {
address 0x039
access_mode RW
modes M_DFF0, M_DFF1, M_SCSI
count 5
field LQIRETRY 0x80
field LQICONTINUE 0x40
field LQITOIDLE 0x20
@ -1528,6 +1558,7 @@ register SCSISEQ1 {
address 0x03B
access_mode RW
modes M_DFF0, M_DFF1, M_SCSI
count 8
field MANUALCTL 0x40
field ENSELI 0x20
field ENRSELI 0x10
@ -1667,6 +1698,9 @@ register SCSISIGO {
}
}
/*
* SCSI Control Signal In
*/
register SCSISIGI {
address 0x041
access_mode RO
@ -1703,6 +1737,7 @@ register MULTARGID {
access_mode RW
modes M_CFG
size 2
count 2
}
/*
@ -1758,6 +1793,7 @@ register TARGIDIN {
address 0x048
access_mode RO
modes M_DFF0, M_DFF1, M_SCSI
count 2
field CLKOUT 0x80
field TARGID 0x0F
}
@ -1798,6 +1834,7 @@ register OPTIONMODE {
address 0x04A
access_mode RW
modes M_CFG
count 4
field BIOSCANCTL 0x80
field AUTOACKEN 0x40
field BIASCANCTL 0x20
@ -1850,6 +1887,7 @@ register SIMODE0 {
address 0x04B
access_mode RW
modes M_CFG
count 8
field ENSELDO 0x40
field ENSELDI 0x20
field ENSELINGO 0x10
@ -1945,6 +1983,7 @@ register PERRDIAG {
address 0x04E
access_mode RO
modes M_DFF0, M_DFF1, M_SCSI
count 3
field HIZERO 0x80
field HIPERR 0x40
field PREVPHASE 0x20
@ -1962,6 +2001,7 @@ register LQISTATE {
address 0x04E
access_mode RO
modes M_CFG
count 6
}
/*
@ -1971,6 +2011,7 @@ register SOFFCNT {
address 0x04F
access_mode RO
modes M_DFF0, M_DFF1, M_SCSI
count 1
}
/*
@ -1980,6 +2021,7 @@ register LQOSTATE {
address 0x04F
access_mode RO
modes M_CFG
count 2
}
/*
@ -1989,6 +2031,7 @@ register LQISTAT0 {
address 0x050
access_mode RO
modes M_DFF0, M_DFF1, M_SCSI
count 2
field LQIATNQAS 0x20
field LQICRCT1 0x10
field LQICRCT2 0x08
@ -2004,6 +2047,7 @@ register CLRLQIINT0 {
address 0x050
access_mode WO
modes M_DFF0, M_DFF1, M_SCSI
count 1
field CLRLQIATNQAS 0x20
field CLRLQICRCT1 0x10
field CLRLQICRCT2 0x08
@ -2019,6 +2063,7 @@ register LQIMODE0 {
address 0x050
access_mode RW
modes M_CFG
count 3
field ENLQIATNQASK 0x20
field ENLQICRCT1 0x10
field ENLQICRCT2 0x08
@ -2034,6 +2079,7 @@ register LQISTAT1 {
address 0x051
access_mode RO
modes M_DFF0, M_DFF1, M_SCSI
count 3
field LQIPHASE_LQ 0x80
field LQIPHASE_NLQ 0x40
field LQIABORT 0x20
@ -2051,6 +2097,7 @@ register CLRLQIINT1 {
address 0x051
access_mode WO
modes M_DFF0, M_DFF1, M_SCSI
count 4
field CLRLQIPHASE_LQ 0x80
field CLRLQIPHASE_NLQ 0x40
field CLRLIQABORT 0x20
@ -2068,6 +2115,7 @@ register LQIMODE1 {
address 0x051
access_mode RW
modes M_CFG
count 4
field ENLQIPHASE_LQ 0x80 /* LQIPHASE1 */
field ENLQIPHASE_NLQ 0x40 /* LQIPHASE2 */
field ENLIQABORT 0x20
@ -2102,6 +2150,7 @@ register SSTAT3 {
address 0x053
access_mode RO
modes M_DFF0, M_DFF1, M_SCSI
count 3
field NTRAMPERR 0x02
field OSRAMPERR 0x01
}
@ -2113,6 +2162,7 @@ register CLRSINT3 {
address 0x053
access_mode WO
modes M_DFF0, M_DFF1, M_SCSI
count 3
field CLRNTRAMPERR 0x02
field CLROSRAMPERR 0x01
}
@ -2124,6 +2174,7 @@ register SIMODE3 {
address 0x053
access_mode RW
modes M_CFG
count 4
field ENNTRAMPERR 0x02
field ENOSRAMPERR 0x01
}
@ -2135,6 +2186,7 @@ register LQOSTAT0 {
address 0x054
access_mode RO
modes M_DFF0, M_DFF1, M_SCSI
count 2
field LQOTARGSCBPERR 0x10
field LQOSTOPT2 0x08
field LQOATNLQ 0x04
@ -2149,6 +2201,7 @@ register CLRLQOINT0 {
address 0x054
access_mode WO
modes M_DFF0, M_DFF1, M_SCSI
count 3
field CLRLQOTARGSCBPERR 0x10
field CLRLQOSTOPT2 0x08
field CLRLQOATNLQ 0x04
@ -2163,6 +2216,7 @@ register LQOMODE0 {
address 0x054
access_mode RW
modes M_CFG
count 4
field ENLQOTARGSCBPERR 0x10
field ENLQOSTOPT2 0x08
field ENLQOATNLQ 0x04
@ -2191,6 +2245,7 @@ register CLRLQOINT1 {
address 0x055
access_mode WO
modes M_DFF0, M_DFF1, M_SCSI
count 7
field CLRLQOINITSCBPERR 0x10
field CLRLQOSTOPI2 0x08
field CLRLQOBADQAS 0x04
@ -2205,6 +2260,7 @@ register LQOMODE1 {
address 0x055
access_mode RW
modes M_CFG
count 4
field ENLQOINITSCBPERR 0x10
field ENLQOSTOPI2 0x08
field ENLQOBADQAS 0x04
@ -2232,6 +2288,7 @@ register OS_SPACE_CNT {
address 0x056
access_mode RO
modes M_CFG
count 2
}
/*
@ -2286,13 +2343,19 @@ register NEXTSCB {
modes M_SCSI
}
/* Rev B only. */
/*
* LQO SCSI Control
* (Rev B only.)
*/
register LQOSCSCTL {
address 0x05A
access_mode RW
size 1
modes M_CFG
count 1
field LQOH2A_VERSION 0x80
field LQOBUSETDLY 0x40
field LQONOHOLDLACK 0x02
field LQONOCHKOVER 0x01
}
@ -2459,6 +2522,7 @@ register NEGPERIOD {
address 0x061
access_mode RW
modes M_SCSI
count 1
}
/*
@ -2478,6 +2542,7 @@ register NEGOFFSET {
address 0x062
access_mode RW
modes M_SCSI
count 1
}
/*
@ -2487,6 +2552,7 @@ register NEGPPROPTS {
address 0x063
access_mode RW
modes M_SCSI
count 1
field PPROPT_PACE 0x08
field PPROPT_QAS 0x04
field PPROPT_DT 0x02
@ -2516,12 +2582,19 @@ register ANNEXCOL {
address 0x065
access_mode RW
modes M_SCSI
count 7
}
/*
* SCSI Check
* (Rev. B only)
*/
register SCSCHKN {
address 0x066
access_mode RW
modes M_CFG
count 1
field BIDICHKDIS 0x80
field STSELSKIDDIS 0x40
field CURRFIFODEF 0x20
field WIDERESEN 0x10
@ -2561,6 +2634,7 @@ register ANNEXDAT {
address 0x066
access_mode RW
modes M_SCSI
count 3
}
/*
@ -2596,6 +2670,7 @@ register TOWNID {
address 0x069
access_mode RW
modes M_SCSI
count 2
}
/*
@ -2737,6 +2812,7 @@ register SCBAUTOPTR {
address 0x0AB
access_mode RW
modes M_CFG
count 1
field AUSCBPTR_EN 0x80
field SCBPTR_ADDR 0x38
field SCBPTR_OFF 0x07
@ -2881,6 +2957,7 @@ register BRDDAT {
address 0x0B8
access_mode RW
modes M_SCSI
count 2
}
/*
@ -2890,6 +2967,7 @@ register BRDCTL {
address 0x0B9
access_mode RW
modes M_SCSI
count 7
field FLXARBACK 0x80
field FLXARBREQ 0x40
field BRDADDR 0x38
@ -2905,6 +2983,7 @@ register SEEADR {
address 0x0BA
access_mode RW
modes M_SCSI
count 4
}
/*
@ -2915,6 +2994,7 @@ register SEEDAT {
access_mode RW
size 2
modes M_SCSI
count 4
}
/*
@ -2924,6 +3004,7 @@ register SEESTAT {
address 0x0BE
access_mode RO
modes M_SCSI
count 1
field INIT_DONE 0x80
field SEEOPCODE 0x70
field LDALTID_L 0x08
@ -2939,6 +3020,7 @@ register SEECTL {
address 0x0BE
access_mode RW
modes M_SCSI
count 4
field SEEOPCODE 0x70 {
SEEOP_ERASE 0x70,
SEEOP_READ 0x60,
@ -3000,6 +3082,7 @@ register DSPDATACTL {
address 0x0C1
access_mode RW
modes M_CFG
count 3
field BYPASSENAB 0x80
field DESQDIS 0x10
field RCVROFFSTDIS 0x04
@ -3058,6 +3141,7 @@ register DSPSELECT {
address 0x0C4
access_mode RW
modes M_CFG
count 1
field AUTOINCEN 0x80
field DSPSEL 0x1F
}
@ -3071,6 +3155,7 @@ register WRTBIASCTL {
address 0x0C5
access_mode WO
modes M_CFG
count 3
field AUTOXBCDIS 0x80
field XMITMANVAL 0x3F
}
@ -3196,7 +3281,8 @@ register OVLYADDR {
*/
register SEQCTL0 {
address 0x0D6
access_mode RW
access_mode RW
count 11
field PERRORDIS 0x80
field PAUSEDIS 0x40
field FAILDIS 0x20
@ -3226,7 +3312,8 @@ register SEQCTL1 {
*/
register FLAGS {
address 0x0D8
access_mode RO
access_mode RO
count 23
field ZERO 0x02
field CARRY 0x01
}
@ -3255,7 +3342,8 @@ register SEQINTCTL {
*/
register SEQRAM {
address 0x0DA
access_mode RW
access_mode RW
count 2
}
/*
@ -3266,6 +3354,7 @@ register PRGMCNT {
address 0x0DE
access_mode RW
size 2
count 5
}
/*
@ -3273,7 +3362,7 @@ register PRGMCNT {
*/
register ACCUM {
address 0x0E0
access_mode RW
access_mode RW
accumulator
}
@ -3401,6 +3490,7 @@ register INTVEC1_ADDR {
access_mode RW
size 2
modes M_CFG
count 1
}
/*
@ -3412,6 +3502,7 @@ register CURADDR {
access_mode RW
size 2
modes M_SCSI
count 2
}
/*
@ -3423,6 +3514,7 @@ register INTVEC2_ADDR {
access_mode RW
size 2
modes M_CFG
count 1
}
/*
@ -3579,6 +3671,7 @@ scratch_ram {
/* Parameters for DMA Logic */
DMAPARAMS {
size 1
count 8
field PRELOADEN 0x80
field WIDEODD 0x40
field SCSIEN 0x20
@ -3648,9 +3741,11 @@ scratch_ram {
*/
KERNEL_TQINPOS {
size 1
count 1
}
TQINPOS {
TQINPOS {
size 1
count 8
}
/*
* Base address of our shared data with the kernel driver in host
@ -3681,6 +3776,7 @@ scratch_ram {
}
ARG_2 {
size 1
count 1
alias RETURN_2
}
@ -3698,6 +3794,7 @@ scratch_ram {
*/
SCSISEQ_TEMPLATE {
size 1
count 7
field MANUALCTL 0x40
field ENSELI 0x20
field ENRSELI 0x10
@ -3711,6 +3808,7 @@ scratch_ram {
*/
INITIATOR_TAG {
size 1
count 1
}
SEQ_FLAGS2 {
@ -3777,6 +3875,7 @@ scratch_ram {
*/
CMDSIZE_TABLE {
size 8
count 8
}
/*
* When an SCB with the MK_MESSAGE flag is
@ -3803,8 +3902,8 @@ scratch_ram {
/************************* Hardware SCB Definition ****************************/
scb {
address 0x180
size 64
modes 0, 1, 2, 3
size 64
modes 0, 1, 2, 3
SCB_RESIDUAL_DATACNT {
size 4
alias SCB_CDB_STORE

View File

@ -52,7 +52,7 @@
/***************************** Lookup Tables **********************************/
static char *ahd_chip_names[] =
static const char *const ahd_chip_names[] =
{
"NONE",
"aic7901",
@ -66,10 +66,10 @@ static const u_int num_chip_names = ARRAY_SIZE(ahd_chip_names);
*/
struct ahd_hard_error_entry {
uint8_t errno;
char *errmesg;
const char *errmesg;
};
static struct ahd_hard_error_entry ahd_hard_errors[] = {
static const struct ahd_hard_error_entry ahd_hard_errors[] = {
{ DSCTMOUT, "Discard Timer has timed out" },
{ ILLOPCODE, "Illegal Opcode in sequencer program" },
{ SQPARERR, "Sequencer Parity Error" },
@ -79,7 +79,7 @@ static struct ahd_hard_error_entry ahd_hard_errors[] = {
};
static const u_int num_errors = ARRAY_SIZE(ahd_hard_errors);
static struct ahd_phase_table_entry ahd_phase_table[] =
static const struct ahd_phase_table_entry ahd_phase_table[] =
{
{ P_DATAOUT, MSG_NOOP, "in Data-out phase" },
{ P_DATAIN, MSG_INITIATOR_DET_ERR, "in Data-in phase" },
@ -213,7 +213,7 @@ static void ahd_dumpseq(struct ahd_softc *ahd);
#endif
static void ahd_loadseq(struct ahd_softc *ahd);
static int ahd_check_patch(struct ahd_softc *ahd,
struct patch **start_patch,
const struct patch **start_patch,
u_int start_instr, u_int *skip_addr);
static u_int ahd_resolve_seqaddr(struct ahd_softc *ahd,
u_int address);
@ -254,7 +254,7 @@ static void ahd_freeze_devq(struct ahd_softc *ahd,
struct scb *scb);
static void ahd_handle_scb_status(struct ahd_softc *ahd,
struct scb *scb);
static struct ahd_phase_table_entry* ahd_lookup_phase_entry(int phase);
static const struct ahd_phase_table_entry* ahd_lookup_phase_entry(int phase);
static void ahd_shutdown(void *arg);
static void ahd_update_coalescing_values(struct ahd_softc *ahd,
u_int timer,
@ -266,8 +266,774 @@ static int ahd_match_scb(struct ahd_softc *ahd, struct scb *scb,
int target, char channel, int lun,
u_int tag, role_t role);
/******************************** Private Inlines *****************************/
static void ahd_reset_cmds_pending(struct ahd_softc *ahd);
/*************************** Interrupt Services *******************************/
static void ahd_run_qoutfifo(struct ahd_softc *ahd);
#ifdef AHD_TARGET_MODE
static void ahd_run_tqinfifo(struct ahd_softc *ahd, int paused);
#endif
static void ahd_handle_hwerrint(struct ahd_softc *ahd);
static void ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat);
static void ahd_handle_scsiint(struct ahd_softc *ahd,
u_int intstat);
/************************ Sequencer Execution Control *************************/
void
ahd_set_modes(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst)
{
if (ahd->src_mode == src && ahd->dst_mode == dst)
return;
#ifdef AHD_DEBUG
if (ahd->src_mode == AHD_MODE_UNKNOWN
|| ahd->dst_mode == AHD_MODE_UNKNOWN)
panic("Setting mode prior to saving it.\n");
if ((ahd_debug & AHD_SHOW_MODEPTR) != 0)
printf("%s: Setting mode 0x%x\n", ahd_name(ahd),
ahd_build_mode_state(ahd, src, dst));
#endif
ahd_outb(ahd, MODE_PTR, ahd_build_mode_state(ahd, src, dst));
ahd->src_mode = src;
ahd->dst_mode = dst;
}
static void
ahd_update_modes(struct ahd_softc *ahd)
{
ahd_mode_state mode_ptr;
ahd_mode src;
ahd_mode dst;
mode_ptr = ahd_inb(ahd, MODE_PTR);
#ifdef AHD_DEBUG
if ((ahd_debug & AHD_SHOW_MODEPTR) != 0)
printf("Reading mode 0x%x\n", mode_ptr);
#endif
ahd_extract_mode_state(ahd, mode_ptr, &src, &dst);
ahd_known_modes(ahd, src, dst);
}
static void
ahd_assert_modes(struct ahd_softc *ahd, ahd_mode srcmode,
ahd_mode dstmode, const char *file, int line)
{
#ifdef AHD_DEBUG
if ((srcmode & AHD_MK_MSK(ahd->src_mode)) == 0
|| (dstmode & AHD_MK_MSK(ahd->dst_mode)) == 0) {
panic("%s:%s:%d: Mode assertion failed.\n",
ahd_name(ahd), file, line);
}
#endif
}
#define AHD_ASSERT_MODES(ahd, source, dest) \
ahd_assert_modes(ahd, source, dest, __FILE__, __LINE__);
ahd_mode_state
ahd_save_modes(struct ahd_softc *ahd)
{
if (ahd->src_mode == AHD_MODE_UNKNOWN
|| ahd->dst_mode == AHD_MODE_UNKNOWN)
ahd_update_modes(ahd);
return (ahd_build_mode_state(ahd, ahd->src_mode, ahd->dst_mode));
}
void
ahd_restore_modes(struct ahd_softc *ahd, ahd_mode_state state)
{
ahd_mode src;
ahd_mode dst;
ahd_extract_mode_state(ahd, state, &src, &dst);
ahd_set_modes(ahd, src, dst);
}
/*
* Determine whether the sequencer has halted code execution.
* Returns non-zero status if the sequencer is stopped.
*/
int
ahd_is_paused(struct ahd_softc *ahd)
{
return ((ahd_inb(ahd, HCNTRL) & PAUSE) != 0);
}
/*
* Request that the sequencer stop and wait, indefinitely, for it
* to stop. The sequencer will only acknowledge that it is paused
* once it has reached an instruction boundary and PAUSEDIS is
* cleared in the SEQCTL register. The sequencer may use PAUSEDIS
* for critical sections.
*/
void
ahd_pause(struct ahd_softc *ahd)
{
ahd_outb(ahd, HCNTRL, ahd->pause);
/*
* Since the sequencer can disable pausing in a critical section, we
* must loop until it actually stops.
*/
while (ahd_is_paused(ahd) == 0)
;
}
/*
* Allow the sequencer to continue program execution.
* We check here to ensure that no additional interrupt
* sources that would cause the sequencer to halt have been
* asserted. If, for example, a SCSI bus reset is detected
* while we are fielding a different, pausing, interrupt type,
* we don't want to release the sequencer before going back
* into our interrupt handler and dealing with this new
* condition.
*/
void
ahd_unpause(struct ahd_softc *ahd)
{
/*
* Automatically restore our modes to those saved
* prior to the first change of the mode.
*/
if (ahd->saved_src_mode != AHD_MODE_UNKNOWN
&& ahd->saved_dst_mode != AHD_MODE_UNKNOWN) {
if ((ahd->flags & AHD_UPDATE_PEND_CMDS) != 0)
ahd_reset_cmds_pending(ahd);
ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode);
}
if ((ahd_inb(ahd, INTSTAT) & ~CMDCMPLT) == 0)
ahd_outb(ahd, HCNTRL, ahd->unpause);
ahd_known_modes(ahd, AHD_MODE_UNKNOWN, AHD_MODE_UNKNOWN);
}
/*********************** Scatter Gather List Handling *************************/
void *
ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb,
void *sgptr, dma_addr_t addr, bus_size_t len, int last)
{
scb->sg_count++;
if (sizeof(dma_addr_t) > 4
&& (ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
struct ahd_dma64_seg *sg;
sg = (struct ahd_dma64_seg *)sgptr;
sg->addr = ahd_htole64(addr);
sg->len = ahd_htole32(len | (last ? AHD_DMA_LAST_SEG : 0));
return (sg + 1);
} else {
struct ahd_dma_seg *sg;
sg = (struct ahd_dma_seg *)sgptr;
sg->addr = ahd_htole32(addr & 0xFFFFFFFF);
sg->len = ahd_htole32(len | ((addr >> 8) & 0x7F000000)
| (last ? AHD_DMA_LAST_SEG : 0));
return (sg + 1);
}
}
static void
ahd_setup_scb_common(struct ahd_softc *ahd, struct scb *scb)
{
/* XXX Handle target mode SCBs. */
scb->crc_retry_count = 0;
if ((scb->flags & SCB_PACKETIZED) != 0) {
/* XXX what about ACA?? It is type 4, but TAG_TYPE == 0x3. */
scb->hscb->task_attribute = scb->hscb->control & SCB_TAG_TYPE;
} else {
if (ahd_get_transfer_length(scb) & 0x01)
scb->hscb->task_attribute = SCB_XFERLEN_ODD;
else
scb->hscb->task_attribute = 0;
}
if (scb->hscb->cdb_len <= MAX_CDB_LEN_WITH_SENSE_ADDR
|| (scb->hscb->cdb_len & SCB_CDB_LEN_PTR) != 0)
scb->hscb->shared_data.idata.cdb_plus_saddr.sense_addr =
ahd_htole32(scb->sense_busaddr);
}
static void
ahd_setup_data_scb(struct ahd_softc *ahd, struct scb *scb)
{
/*
* Copy the first SG into the "current" data ponter area.
*/
if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
struct ahd_dma64_seg *sg;
sg = (struct ahd_dma64_seg *)scb->sg_list;
scb->hscb->dataptr = sg->addr;
scb->hscb->datacnt = sg->len;
} else {
struct ahd_dma_seg *sg;
uint32_t *dataptr_words;
sg = (struct ahd_dma_seg *)scb->sg_list;
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;
high_addr = ahd_le32toh(sg->len) & 0x7F000000;
scb->hscb->dataptr |= ahd_htole64(high_addr << 8);
}
scb->hscb->datacnt = sg->len;
}
/*
* Note where to find the SG entries in bus space.
* We also set the full residual flag which the
* sequencer will clear as soon as a data transfer
* occurs.
*/
scb->hscb->sgptr = ahd_htole32(scb->sg_list_busaddr|SG_FULL_RESID);
}
static void
ahd_setup_noxfer_scb(struct ahd_softc *ahd, struct scb *scb)
{
scb->hscb->sgptr = ahd_htole32(SG_LIST_NULL);
scb->hscb->dataptr = 0;
scb->hscb->datacnt = 0;
}
/************************** Memory mapping routines ***************************/
static void *
ahd_sg_bus_to_virt(struct ahd_softc *ahd, struct scb *scb, uint32_t sg_busaddr)
{
dma_addr_t sg_offset;
/* sg_list_phys points to entry 1, not 0 */
sg_offset = sg_busaddr - (scb->sg_list_busaddr - ahd_sg_size(ahd));
return ((uint8_t *)scb->sg_list + sg_offset);
}
static uint32_t
ahd_sg_virt_to_bus(struct ahd_softc *ahd, struct scb *scb, void *sg)
{
dma_addr_t sg_offset;
/* sg_list_phys points to entry 1, not 0 */
sg_offset = ((uint8_t *)sg - (uint8_t *)scb->sg_list)
- ahd_sg_size(ahd);
return (scb->sg_list_busaddr + sg_offset);
}
static void
ahd_sync_scb(struct ahd_softc *ahd, struct scb *scb, int op)
{
ahd_dmamap_sync(ahd, ahd->scb_data.hscb_dmat,
scb->hscb_map->dmamap,
/*offset*/(uint8_t*)scb->hscb - scb->hscb_map->vaddr,
/*len*/sizeof(*scb->hscb), op);
}
void
ahd_sync_sglist(struct ahd_softc *ahd, struct scb *scb, int op)
{
if (scb->sg_count == 0)
return;
ahd_dmamap_sync(ahd, ahd->scb_data.sg_dmat,
scb->sg_map->dmamap,
/*offset*/scb->sg_list_busaddr - ahd_sg_size(ahd),
/*len*/ahd_sg_size(ahd) * scb->sg_count, op);
}
static void
ahd_sync_sense(struct ahd_softc *ahd, struct scb *scb, int op)
{
ahd_dmamap_sync(ahd, ahd->scb_data.sense_dmat,
scb->sense_map->dmamap,
/*offset*/scb->sense_busaddr,
/*len*/AHD_SENSE_BUFSIZE, op);
}
#ifdef AHD_TARGET_MODE
static uint32_t
ahd_targetcmd_offset(struct ahd_softc *ahd, u_int index)
{
return (((uint8_t *)&ahd->targetcmds[index])
- (uint8_t *)ahd->qoutfifo);
}
#endif
/*********************** Miscelaneous Support Functions ***********************/
/*
* Return pointers to the transfer negotiation information
* for the specified our_id/remote_id pair.
*/
struct ahd_initiator_tinfo *
ahd_fetch_transinfo(struct ahd_softc *ahd, char channel, u_int our_id,
u_int remote_id, struct ahd_tmode_tstate **tstate)
{
/*
* Transfer data structures are stored from the perspective
* of the target role. Since the parameters for a connection
* in the initiator role to a given target are the same as
* when the roles are reversed, we pretend we are the target.
*/
if (channel == 'B')
our_id += 8;
*tstate = ahd->enabled_targets[our_id];
return (&(*tstate)->transinfo[remote_id]);
}
uint16_t
ahd_inw(struct ahd_softc *ahd, u_int port)
{
/*
* Read high byte first as some registers increment
* or have other side effects when the low byte is
* read.
*/
uint16_t r = ahd_inb(ahd, port+1) << 8;
return r | ahd_inb(ahd, port);
}
void
ahd_outw(struct ahd_softc *ahd, u_int port, u_int value)
{
/*
* Write low byte first to accomodate registers
* such as PRGMCNT where the order maters.
*/
ahd_outb(ahd, port, value & 0xFF);
ahd_outb(ahd, port+1, (value >> 8) & 0xFF);
}
uint32_t
ahd_inl(struct ahd_softc *ahd, u_int port)
{
return ((ahd_inb(ahd, port))
| (ahd_inb(ahd, port+1) << 8)
| (ahd_inb(ahd, port+2) << 16)
| (ahd_inb(ahd, port+3) << 24));
}
void
ahd_outl(struct ahd_softc *ahd, u_int port, uint32_t value)
{
ahd_outb(ahd, port, (value) & 0xFF);
ahd_outb(ahd, port+1, ((value) >> 8) & 0xFF);
ahd_outb(ahd, port+2, ((value) >> 16) & 0xFF);
ahd_outb(ahd, port+3, ((value) >> 24) & 0xFF);
}
uint64_t
ahd_inq(struct ahd_softc *ahd, u_int port)
{
return ((ahd_inb(ahd, port))
| (ahd_inb(ahd, port+1) << 8)
| (ahd_inb(ahd, port+2) << 16)
| (ahd_inb(ahd, port+3) << 24)
| (((uint64_t)ahd_inb(ahd, port+4)) << 32)
| (((uint64_t)ahd_inb(ahd, port+5)) << 40)
| (((uint64_t)ahd_inb(ahd, port+6)) << 48)
| (((uint64_t)ahd_inb(ahd, port+7)) << 56));
}
void
ahd_outq(struct ahd_softc *ahd, u_int port, uint64_t value)
{
ahd_outb(ahd, port, value & 0xFF);
ahd_outb(ahd, port+1, (value >> 8) & 0xFF);
ahd_outb(ahd, port+2, (value >> 16) & 0xFF);
ahd_outb(ahd, port+3, (value >> 24) & 0xFF);
ahd_outb(ahd, port+4, (value >> 32) & 0xFF);
ahd_outb(ahd, port+5, (value >> 40) & 0xFF);
ahd_outb(ahd, port+6, (value >> 48) & 0xFF);
ahd_outb(ahd, port+7, (value >> 56) & 0xFF);
}
u_int
ahd_get_scbptr(struct ahd_softc *ahd)
{
AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
return (ahd_inb(ahd, SCBPTR) | (ahd_inb(ahd, SCBPTR + 1) << 8));
}
void
ahd_set_scbptr(struct ahd_softc *ahd, u_int scbptr)
{
AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
ahd_outb(ahd, SCBPTR, scbptr & 0xFF);
ahd_outb(ahd, SCBPTR+1, (scbptr >> 8) & 0xFF);
}
#if 0 /* unused */
static u_int
ahd_get_hnscb_qoff(struct ahd_softc *ahd)
{
return (ahd_inw_atomic(ahd, HNSCB_QOFF));
}
#endif
static void
ahd_set_hnscb_qoff(struct ahd_softc *ahd, u_int value)
{
ahd_outw_atomic(ahd, HNSCB_QOFF, value);
}
#if 0 /* unused */
static u_int
ahd_get_hescb_qoff(struct ahd_softc *ahd)
{
return (ahd_inb(ahd, HESCB_QOFF));
}
#endif
static void
ahd_set_hescb_qoff(struct ahd_softc *ahd, u_int value)
{
ahd_outb(ahd, HESCB_QOFF, value);
}
static u_int
ahd_get_snscb_qoff(struct ahd_softc *ahd)
{
u_int oldvalue;
AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
oldvalue = ahd_inw(ahd, SNSCB_QOFF);
ahd_outw(ahd, SNSCB_QOFF, oldvalue);
return (oldvalue);
}
static void
ahd_set_snscb_qoff(struct ahd_softc *ahd, u_int value)
{
AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
ahd_outw(ahd, SNSCB_QOFF, value);
}
#if 0 /* unused */
static u_int
ahd_get_sescb_qoff(struct ahd_softc *ahd)
{
AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
return (ahd_inb(ahd, SESCB_QOFF));
}
#endif
static void
ahd_set_sescb_qoff(struct ahd_softc *ahd, u_int value)
{
AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
ahd_outb(ahd, SESCB_QOFF, value);
}
#if 0 /* unused */
static u_int
ahd_get_sdscb_qoff(struct ahd_softc *ahd)
{
AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
return (ahd_inb(ahd, SDSCB_QOFF) | (ahd_inb(ahd, SDSCB_QOFF + 1) << 8));
}
#endif
static void
ahd_set_sdscb_qoff(struct ahd_softc *ahd, u_int value)
{
AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
ahd_outb(ahd, SDSCB_QOFF, value & 0xFF);
ahd_outb(ahd, SDSCB_QOFF+1, (value >> 8) & 0xFF);
}
u_int
ahd_inb_scbram(struct ahd_softc *ahd, u_int offset)
{
u_int value;
/*
* Workaround PCI-X Rev A. hardware bug.
* After a host read of SCB memory, the chip
* may become confused into thinking prefetch
* was required. This starts the discard timer
* running and can cause an unexpected discard
* timer interrupt. The work around is to read
* a normal register prior to the exhaustion of
* the discard timer. The mode pointer register
* has no side effects and so serves well for
* this purpose.
*
* Razor #528
*/
value = ahd_inb(ahd, offset);
if ((ahd->bugs & AHD_PCIX_SCBRAM_RD_BUG) != 0)
ahd_inb(ahd, MODE_PTR);
return (value);
}
u_int
ahd_inw_scbram(struct ahd_softc *ahd, u_int offset)
{
return (ahd_inb_scbram(ahd, offset)
| (ahd_inb_scbram(ahd, offset+1) << 8));
}
static uint32_t
ahd_inl_scbram(struct ahd_softc *ahd, u_int offset)
{
return (ahd_inw_scbram(ahd, offset)
| (ahd_inw_scbram(ahd, offset+2) << 16));
}
static uint64_t
ahd_inq_scbram(struct ahd_softc *ahd, u_int offset)
{
return (ahd_inl_scbram(ahd, offset)
| ((uint64_t)ahd_inl_scbram(ahd, offset+4)) << 32);
}
struct scb *
ahd_lookup_scb(struct ahd_softc *ahd, u_int tag)
{
struct scb* scb;
if (tag >= AHD_SCB_MAX)
return (NULL);
scb = ahd->scb_data.scbindex[tag];
if (scb != NULL)
ahd_sync_scb(ahd, scb,
BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
return (scb);
}
static void
ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb)
{
struct hardware_scb *q_hscb;
struct map_node *q_hscb_map;
uint32_t saved_hscb_busaddr;
/*
* Our queuing method is a bit tricky. The card
* knows in advance which HSCB (by address) to download,
* and we can't disappoint it. To achieve this, the next
* HSCB to download is saved off in ahd->next_queued_hscb.
* When we are called to queue "an arbitrary scb",
* we copy the contents of the incoming HSCB to the one
* the sequencer knows about, swap HSCB pointers and
* finally assign the SCB to the tag indexed location
* in the scb_array. This makes sure that we can still
* locate the correct SCB by SCB_TAG.
*/
q_hscb = ahd->next_queued_hscb;
q_hscb_map = ahd->next_queued_hscb_map;
saved_hscb_busaddr = q_hscb->hscb_busaddr;
memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb));
q_hscb->hscb_busaddr = saved_hscb_busaddr;
q_hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr;
/* Now swap HSCB pointers. */
ahd->next_queued_hscb = scb->hscb;
ahd->next_queued_hscb_map = scb->hscb_map;
scb->hscb = q_hscb;
scb->hscb_map = q_hscb_map;
/* Now define the mapping from tag to SCB in the scbindex */
ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb;
}
/*
* Tell the sequencer about a new transaction to execute.
*/
void
ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb)
{
ahd_swap_with_next_hscb(ahd, scb);
if (SCBID_IS_NULL(SCB_GET_TAG(scb)))
panic("Attempt to queue invalid SCB tag %x\n",
SCB_GET_TAG(scb));
/*
* Keep a history of SCBs we've downloaded in the qinfifo.
*/
ahd->qinfifo[AHD_QIN_WRAP(ahd->qinfifonext)] = SCB_GET_TAG(scb);
ahd->qinfifonext++;
if (scb->sg_count != 0)
ahd_setup_data_scb(ahd, scb);
else
ahd_setup_noxfer_scb(ahd, scb);
ahd_setup_scb_common(ahd, scb);
/*
* Make sure our data is consistent from the
* perspective of the adapter.
*/
ahd_sync_scb(ahd, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
#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 %d:0x%x bus addr 0x%x - 0x%x%x/0x%x\n",
ahd_name(ahd),
SCB_GET_TAG(scb), scb->hscb->scsiid,
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 */
ahd_set_hnscb_qoff(ahd, ahd->qinfifonext);
}
/************************** Interrupt Processing ******************************/
static void
ahd_sync_qoutfifo(struct ahd_softc *ahd, int op)
{
ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
/*offset*/0,
/*len*/AHD_SCB_MAX * sizeof(struct ahd_completion), op);
}
static void
ahd_sync_tqinfifo(struct ahd_softc *ahd, int op)
{
#ifdef AHD_TARGET_MODE
if ((ahd->flags & AHD_TARGETROLE) != 0) {
ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
ahd->shared_data_map.dmamap,
ahd_targetcmd_offset(ahd, 0),
sizeof(struct target_cmd) * AHD_TMODE_CMDS,
op);
}
#endif
}
/*
* See if the firmware has posted any completed commands
* into our in-core command complete fifos.
*/
#define AHD_RUN_QOUTFIFO 0x1
#define AHD_RUN_TQINFIFO 0x2
static u_int
ahd_check_cmdcmpltqueues(struct ahd_softc *ahd)
{
u_int retval;
retval = 0;
ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
/*offset*/ahd->qoutfifonext * sizeof(*ahd->qoutfifo),
/*len*/sizeof(*ahd->qoutfifo), BUS_DMASYNC_POSTREAD);
if (ahd->qoutfifo[ahd->qoutfifonext].valid_tag
== ahd->qoutfifonext_valid_tag)
retval |= AHD_RUN_QOUTFIFO;
#ifdef AHD_TARGET_MODE
if ((ahd->flags & AHD_TARGETROLE) != 0
&& (ahd->flags & AHD_TQINFIFO_BLOCKED) == 0) {
ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
ahd->shared_data_map.dmamap,
ahd_targetcmd_offset(ahd, ahd->tqinfifofnext),
/*len*/sizeof(struct target_cmd),
BUS_DMASYNC_POSTREAD);
if (ahd->targetcmds[ahd->tqinfifonext].cmd_valid != 0)
retval |= AHD_RUN_TQINFIFO;
}
#endif
return (retval);
}
/*
* Catch an interrupt from the adapter
*/
int
ahd_intr(struct ahd_softc *ahd)
{
u_int intstat;
if ((ahd->pause & INTEN) == 0) {
/*
* Our interrupt is not enabled on the chip
* and may be disabled for re-entrancy reasons,
* so just return. This is likely just a shared
* interrupt.
*/
return (0);
}
/*
* Instead of directly reading the interrupt status register,
* infer the cause of the interrupt by checking our in-core
* completion queues. This avoids a costly PCI bus read in
* most cases.
*/
if ((ahd->flags & AHD_ALL_INTERRUPTS) == 0
&& (ahd_check_cmdcmpltqueues(ahd) != 0))
intstat = CMDCMPLT;
else
intstat = ahd_inb(ahd, INTSTAT);
if ((intstat & INT_PEND) == 0)
return (0);
if (intstat & CMDCMPLT) {
ahd_outb(ahd, CLRINT, CLRCMDINT);
/*
* Ensure that the chip sees that we've cleared
* this interrupt before we walk the output fifo.
* Otherwise, we may, due to posted bus writes,
* clear the interrupt after we finish the scan,
* and after the sequencer has added new entries
* and asserted the interrupt again.
*/
if ((ahd->bugs & AHD_INTCOLLISION_BUG) != 0) {
if (ahd_is_paused(ahd)) {
/*
* Potentially lost SEQINT.
* If SEQINTCODE is non-zero,
* simulate the SEQINT.
*/
if (ahd_inb(ahd, SEQINTCODE) != NO_SEQINT)
intstat |= SEQINT;
}
} else {
ahd_flush_device_writes(ahd);
}
ahd_run_qoutfifo(ahd);
ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket]++;
ahd->cmdcmplt_total++;
#ifdef AHD_TARGET_MODE
if ((ahd->flags & AHD_TARGETROLE) != 0)
ahd_run_tqinfifo(ahd, /*paused*/FALSE);
#endif
}
/*
* 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);
} else if ((intstat & (PCIINT|SPLTINT)) != 0) {
ahd->bus_intr(ahd);
} else {
if ((intstat & SEQINT) != 0)
ahd_handle_seqint(ahd, intstat);
if ((intstat & SCSIINT) != 0)
ahd_handle_scsiint(ahd, intstat);
}
return (1);
}
/******************************** Private Inlines *****************************/
static __inline void
ahd_assert_atn(struct ahd_softc *ahd)
{
@ -280,7 +1046,7 @@ ahd_assert_atn(struct ahd_softc *ahd)
* are currently in a packetized transfer. We could
* just as easily be sending or receiving a message.
*/
static __inline int
static int
ahd_currently_packetized(struct ahd_softc *ahd)
{
ahd_mode_state saved_modes;
@ -896,7 +1662,7 @@ clrchn:
* a copy of the first byte (little endian) of the sgptr
* hscb field.
*/
void
static void
ahd_run_qoutfifo(struct ahd_softc *ahd)
{
struct ahd_completion *completion;
@ -935,7 +1701,7 @@ ahd_run_qoutfifo(struct ahd_softc *ahd)
}
/************************* Interrupt Handling *********************************/
void
static void
ahd_handle_hwerrint(struct ahd_softc *ahd)
{
/*
@ -1009,7 +1775,7 @@ ahd_dump_sglist(struct scb *scb)
}
#endif /* AHD_DEBUG */
void
static void
ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
{
u_int seqintcode;
@ -1621,7 +2387,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
ahd_unpause(ahd);
}
void
static void
ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
{
struct scb *scb;
@ -3571,11 +4337,11 @@ ahd_print_devinfo(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
devinfo->target, devinfo->lun);
}
static struct ahd_phase_table_entry*
static const struct ahd_phase_table_entry*
ahd_lookup_phase_entry(int phase)
{
struct ahd_phase_table_entry *entry;
struct ahd_phase_table_entry *last_entry;
const struct ahd_phase_table_entry *entry;
const struct ahd_phase_table_entry *last_entry;
/*
* num_phases doesn't include the default entry which
@ -3941,7 +4707,7 @@ ahd_clear_msg_state(struct ahd_softc *ahd)
*/
static void
ahd_handle_message_phase(struct ahd_softc *ahd)
{
{
struct ahd_devinfo devinfo;
u_int bus_phase;
int end_session;
@ -5983,8 +6749,7 @@ found:
*/
void
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;
@ -6272,6 +7037,24 @@ static const char *termstat_strings[] = {
"Not Configured"
};
/***************************** Timer Facilities *******************************/
#define ahd_timer_init init_timer
#define ahd_timer_stop del_timer_sync
typedef void ahd_linux_callback_t (u_long);
static void
ahd_timer_reset(ahd_timer_t *timer, int usec, ahd_callback_t *func, void *arg)
{
struct ahd_softc *ahd;
ahd = (struct ahd_softc *)arg;
del_timer(timer);
timer->data = (u_long)arg;
timer->expires = jiffies + (usec * HZ)/1000000;
timer->function = (ahd_linux_callback_t*)func;
add_timer(timer);
}
/*
* Start the board, ready for normal operation
*/
@ -7370,7 +8153,7 @@ ahd_qinfifo_count(struct ahd_softc *ahd)
+ ARRAY_SIZE(ahd->qinfifo) - wrap_qinpos);
}
void
static void
ahd_reset_cmds_pending(struct ahd_softc *ahd)
{
struct scb *scb;
@ -8571,7 +9354,7 @@ ahd_loadseq(struct ahd_softc *ahd)
struct cs cs_table[num_critical_sections];
u_int begin_set[num_critical_sections];
u_int end_set[num_critical_sections];
struct patch *cur_patch;
const struct patch *cur_patch;
u_int cs_count;
u_int cur_cs;
u_int i;
@ -8726,11 +9509,11 @@ ahd_loadseq(struct ahd_softc *ahd)
}
static int
ahd_check_patch(struct ahd_softc *ahd, struct patch **start_patch,
ahd_check_patch(struct ahd_softc *ahd, const struct patch **start_patch,
u_int start_instr, u_int *skip_addr)
{
struct patch *cur_patch;
struct patch *last_patch;
const struct patch *cur_patch;
const struct patch *last_patch;
u_int num_patches;
num_patches = ARRAY_SIZE(patches);
@ -8764,7 +9547,7 @@ ahd_check_patch(struct ahd_softc *ahd, struct patch **start_patch,
static u_int
ahd_resolve_seqaddr(struct ahd_softc *ahd, u_int address)
{
struct patch *cur_patch;
const struct patch *cur_patch;
int address_offset;
u_int skip_addr;
u_int i;
@ -8895,7 +9678,7 @@ sized:
}
int
ahd_print_register(ahd_reg_parse_entry_t *table, u_int num_entries,
ahd_print_register(const ahd_reg_parse_entry_t *table, u_int num_entries,
const char *name, u_int address, u_int value,
u_int *cur_column, u_int wrap_point)
{
@ -9886,7 +10669,7 @@ ahd_update_scsiid(struct ahd_softc *ahd, u_int targid_mask)
#endif
}
void
static void
ahd_run_tqinfifo(struct ahd_softc *ahd, int paused)
{
struct target_cmd *cmd;

View File

@ -63,18 +63,15 @@ static __inline ahd_mode_state ahd_build_mode_state(struct ahd_softc *ahd,
static __inline void ahd_extract_mode_state(struct ahd_softc *ahd,
ahd_mode_state state,
ahd_mode *src, ahd_mode *dst);
static __inline void ahd_set_modes(struct ahd_softc *ahd, ahd_mode src,
ahd_mode dst);
static __inline void ahd_update_modes(struct ahd_softc *ahd);
static __inline void ahd_assert_modes(struct ahd_softc *ahd, ahd_mode srcmode,
ahd_mode dstmode, const char *file,
int line);
static __inline ahd_mode_state ahd_save_modes(struct ahd_softc *ahd);
static __inline void ahd_restore_modes(struct ahd_softc *ahd,
ahd_mode_state state);
static __inline int ahd_is_paused(struct ahd_softc *ahd);
static __inline void ahd_pause(struct ahd_softc *ahd);
static __inline void ahd_unpause(struct ahd_softc *ahd);
void ahd_set_modes(struct ahd_softc *ahd, ahd_mode src,
ahd_mode dst);
ahd_mode_state ahd_save_modes(struct ahd_softc *ahd);
void ahd_restore_modes(struct ahd_softc *ahd,
ahd_mode_state state);
int ahd_is_paused(struct ahd_softc *ahd);
void ahd_pause(struct ahd_softc *ahd);
void ahd_unpause(struct ahd_softc *ahd);
static __inline void
ahd_known_modes(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst)
@ -99,256 +96,16 @@ ahd_extract_mode_state(struct ahd_softc *ahd, ahd_mode_state state,
*dst = (state & DST_MODE) >> DST_MODE_SHIFT;
}
static __inline void
ahd_set_modes(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst)
{
if (ahd->src_mode == src && ahd->dst_mode == dst)
return;
#ifdef AHD_DEBUG
if (ahd->src_mode == AHD_MODE_UNKNOWN
|| ahd->dst_mode == AHD_MODE_UNKNOWN)
panic("Setting mode prior to saving it.\n");
if ((ahd_debug & AHD_SHOW_MODEPTR) != 0)
printf("%s: Setting mode 0x%x\n", ahd_name(ahd),
ahd_build_mode_state(ahd, src, dst));
#endif
ahd_outb(ahd, MODE_PTR, ahd_build_mode_state(ahd, src, dst));
ahd->src_mode = src;
ahd->dst_mode = dst;
}
static __inline void
ahd_update_modes(struct ahd_softc *ahd)
{
ahd_mode_state mode_ptr;
ahd_mode src;
ahd_mode dst;
mode_ptr = ahd_inb(ahd, MODE_PTR);
#ifdef AHD_DEBUG
if ((ahd_debug & AHD_SHOW_MODEPTR) != 0)
printf("Reading mode 0x%x\n", mode_ptr);
#endif
ahd_extract_mode_state(ahd, mode_ptr, &src, &dst);
ahd_known_modes(ahd, src, dst);
}
static __inline void
ahd_assert_modes(struct ahd_softc *ahd, ahd_mode srcmode,
ahd_mode dstmode, const char *file, int line)
{
#ifdef AHD_DEBUG
if ((srcmode & AHD_MK_MSK(ahd->src_mode)) == 0
|| (dstmode & AHD_MK_MSK(ahd->dst_mode)) == 0) {
panic("%s:%s:%d: Mode assertion failed.\n",
ahd_name(ahd), file, line);
}
#endif
}
static __inline ahd_mode_state
ahd_save_modes(struct ahd_softc *ahd)
{
if (ahd->src_mode == AHD_MODE_UNKNOWN
|| ahd->dst_mode == AHD_MODE_UNKNOWN)
ahd_update_modes(ahd);
return (ahd_build_mode_state(ahd, ahd->src_mode, ahd->dst_mode));
}
static __inline void
ahd_restore_modes(struct ahd_softc *ahd, ahd_mode_state state)
{
ahd_mode src;
ahd_mode dst;
ahd_extract_mode_state(ahd, state, &src, &dst);
ahd_set_modes(ahd, src, dst);
}
#define AHD_ASSERT_MODES(ahd, source, dest) \
ahd_assert_modes(ahd, source, dest, __FILE__, __LINE__);
/*
* Determine whether the sequencer has halted code execution.
* Returns non-zero status if the sequencer is stopped.
*/
static __inline int
ahd_is_paused(struct ahd_softc *ahd)
{
return ((ahd_inb(ahd, HCNTRL) & PAUSE) != 0);
}
/*
* Request that the sequencer stop and wait, indefinitely, for it
* to stop. The sequencer will only acknowledge that it is paused
* once it has reached an instruction boundary and PAUSEDIS is
* cleared in the SEQCTL register. The sequencer may use PAUSEDIS
* for critical sections.
*/
static __inline void
ahd_pause(struct ahd_softc *ahd)
{
ahd_outb(ahd, HCNTRL, ahd->pause);
/*
* Since the sequencer can disable pausing in a critical section, we
* must loop until it actually stops.
*/
while (ahd_is_paused(ahd) == 0)
;
}
/*
* Allow the sequencer to continue program execution.
* We check here to ensure that no additional interrupt
* sources that would cause the sequencer to halt have been
* asserted. If, for example, a SCSI bus reset is detected
* while we are fielding a different, pausing, interrupt type,
* we don't want to release the sequencer before going back
* into our interrupt handler and dealing with this new
* condition.
*/
static __inline void
ahd_unpause(struct ahd_softc *ahd)
{
/*
* Automatically restore our modes to those saved
* prior to the first change of the mode.
*/
if (ahd->saved_src_mode != AHD_MODE_UNKNOWN
&& ahd->saved_dst_mode != AHD_MODE_UNKNOWN) {
if ((ahd->flags & AHD_UPDATE_PEND_CMDS) != 0)
ahd_reset_cmds_pending(ahd);
ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode);
}
if ((ahd_inb(ahd, INTSTAT) & ~CMDCMPLT) == 0)
ahd_outb(ahd, HCNTRL, ahd->unpause);
ahd_known_modes(ahd, AHD_MODE_UNKNOWN, AHD_MODE_UNKNOWN);
}
/*********************** Scatter Gather List Handling *************************/
static __inline void *ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb,
void *sgptr, dma_addr_t addr,
bus_size_t len, int last);
static __inline void ahd_setup_scb_common(struct ahd_softc *ahd,
struct scb *scb);
static __inline void ahd_setup_data_scb(struct ahd_softc *ahd,
struct scb *scb);
static __inline void ahd_setup_noxfer_scb(struct ahd_softc *ahd,
struct scb *scb);
static __inline void *
ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb,
void *sgptr, dma_addr_t addr, bus_size_t len, int last)
{
scb->sg_count++;
if (sizeof(dma_addr_t) > 4
&& (ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
struct ahd_dma64_seg *sg;
sg = (struct ahd_dma64_seg *)sgptr;
sg->addr = ahd_htole64(addr);
sg->len = ahd_htole32(len | (last ? AHD_DMA_LAST_SEG : 0));
return (sg + 1);
} else {
struct ahd_dma_seg *sg;
sg = (struct ahd_dma_seg *)sgptr;
sg->addr = ahd_htole32(addr & 0xFFFFFFFF);
sg->len = ahd_htole32(len | ((addr >> 8) & 0x7F000000)
| (last ? AHD_DMA_LAST_SEG : 0));
return (sg + 1);
}
}
static __inline void
ahd_setup_scb_common(struct ahd_softc *ahd, struct scb *scb)
{
/* XXX Handle target mode SCBs. */
scb->crc_retry_count = 0;
if ((scb->flags & SCB_PACKETIZED) != 0) {
/* XXX what about ACA?? It is type 4, but TAG_TYPE == 0x3. */
scb->hscb->task_attribute = scb->hscb->control & SCB_TAG_TYPE;
} else {
if (ahd_get_transfer_length(scb) & 0x01)
scb->hscb->task_attribute = SCB_XFERLEN_ODD;
else
scb->hscb->task_attribute = 0;
}
if (scb->hscb->cdb_len <= MAX_CDB_LEN_WITH_SENSE_ADDR
|| (scb->hscb->cdb_len & SCB_CDB_LEN_PTR) != 0)
scb->hscb->shared_data.idata.cdb_plus_saddr.sense_addr =
ahd_htole32(scb->sense_busaddr);
}
static __inline void
ahd_setup_data_scb(struct ahd_softc *ahd, struct scb *scb)
{
/*
* Copy the first SG into the "current" data ponter area.
*/
if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
struct ahd_dma64_seg *sg;
sg = (struct ahd_dma64_seg *)scb->sg_list;
scb->hscb->dataptr = sg->addr;
scb->hscb->datacnt = sg->len;
} else {
struct ahd_dma_seg *sg;
uint32_t *dataptr_words;
sg = (struct ahd_dma_seg *)scb->sg_list;
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;
high_addr = ahd_le32toh(sg->len) & 0x7F000000;
scb->hscb->dataptr |= ahd_htole64(high_addr << 8);
}
scb->hscb->datacnt = sg->len;
}
/*
* Note where to find the SG entries in bus space.
* We also set the full residual flag which the
* sequencer will clear as soon as a data transfer
* occurs.
*/
scb->hscb->sgptr = ahd_htole32(scb->sg_list_busaddr|SG_FULL_RESID);
}
static __inline void
ahd_setup_noxfer_scb(struct ahd_softc *ahd, struct scb *scb)
{
scb->hscb->sgptr = ahd_htole32(SG_LIST_NULL);
scb->hscb->dataptr = 0;
scb->hscb->datacnt = 0;
}
void *ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb,
void *sgptr, dma_addr_t addr,
bus_size_t len, int last);
/************************** Memory mapping routines ***************************/
static __inline size_t ahd_sg_size(struct ahd_softc *ahd);
static __inline void *
ahd_sg_bus_to_virt(struct ahd_softc *ahd,
struct scb *scb,
uint32_t sg_busaddr);
static __inline uint32_t
ahd_sg_virt_to_bus(struct ahd_softc *ahd,
struct scb *scb,
void *sg);
static __inline void ahd_sync_scb(struct ahd_softc *ahd,
struct scb *scb, int op);
static __inline void ahd_sync_sglist(struct ahd_softc *ahd,
struct scb *scb, int op);
static __inline void ahd_sync_sense(struct ahd_softc *ahd,
struct scb *scb, int op);
static __inline uint32_t
ahd_targetcmd_offset(struct ahd_softc *ahd,
u_int index);
void ahd_sync_sglist(struct ahd_softc *ahd,
struct scb *scb, int op);
static __inline size_t
ahd_sg_size(struct ahd_softc *ahd)
@ -358,104 +115,32 @@ ahd_sg_size(struct ahd_softc *ahd)
return (sizeof(struct ahd_dma_seg));
}
static __inline void *
ahd_sg_bus_to_virt(struct ahd_softc *ahd, struct scb *scb, uint32_t sg_busaddr)
{
dma_addr_t sg_offset;
/* sg_list_phys points to entry 1, not 0 */
sg_offset = sg_busaddr - (scb->sg_list_busaddr - ahd_sg_size(ahd));
return ((uint8_t *)scb->sg_list + sg_offset);
}
static __inline uint32_t
ahd_sg_virt_to_bus(struct ahd_softc *ahd, struct scb *scb, void *sg)
{
dma_addr_t sg_offset;
/* sg_list_phys points to entry 1, not 0 */
sg_offset = ((uint8_t *)sg - (uint8_t *)scb->sg_list)
- ahd_sg_size(ahd);
return (scb->sg_list_busaddr + sg_offset);
}
static __inline void
ahd_sync_scb(struct ahd_softc *ahd, struct scb *scb, int op)
{
ahd_dmamap_sync(ahd, ahd->scb_data.hscb_dmat,
scb->hscb_map->dmamap,
/*offset*/(uint8_t*)scb->hscb - scb->hscb_map->vaddr,
/*len*/sizeof(*scb->hscb), op);
}
static __inline void
ahd_sync_sglist(struct ahd_softc *ahd, struct scb *scb, int op)
{
if (scb->sg_count == 0)
return;
ahd_dmamap_sync(ahd, ahd->scb_data.sg_dmat,
scb->sg_map->dmamap,
/*offset*/scb->sg_list_busaddr - ahd_sg_size(ahd),
/*len*/ahd_sg_size(ahd) * scb->sg_count, op);
}
static __inline void
ahd_sync_sense(struct ahd_softc *ahd, struct scb *scb, int op)
{
ahd_dmamap_sync(ahd, ahd->scb_data.sense_dmat,
scb->sense_map->dmamap,
/*offset*/scb->sense_busaddr,
/*len*/AHD_SENSE_BUFSIZE, op);
}
static __inline uint32_t
ahd_targetcmd_offset(struct ahd_softc *ahd, u_int index)
{
return (((uint8_t *)&ahd->targetcmds[index])
- (uint8_t *)ahd->qoutfifo);
}
/*********************** Miscellaneous Support Functions ***********************/
static __inline struct ahd_initiator_tinfo *
ahd_fetch_transinfo(struct ahd_softc *ahd,
char channel, u_int our_id,
u_int remote_id,
struct ahd_tmode_tstate **tstate);
static __inline uint16_t
ahd_inw(struct ahd_softc *ahd, u_int port);
static __inline void ahd_outw(struct ahd_softc *ahd, u_int port,
u_int value);
static __inline uint32_t
ahd_inl(struct ahd_softc *ahd, u_int port);
static __inline void ahd_outl(struct ahd_softc *ahd, u_int port,
uint32_t value);
static __inline uint64_t
ahd_inq(struct ahd_softc *ahd, u_int port);
static __inline void ahd_outq(struct ahd_softc *ahd, u_int port,
uint64_t value);
static __inline u_int ahd_get_scbptr(struct ahd_softc *ahd);
static __inline void ahd_set_scbptr(struct ahd_softc *ahd, u_int scbptr);
static __inline u_int ahd_get_hnscb_qoff(struct ahd_softc *ahd);
static __inline void ahd_set_hnscb_qoff(struct ahd_softc *ahd, u_int value);
static __inline u_int ahd_get_hescb_qoff(struct ahd_softc *ahd);
static __inline void ahd_set_hescb_qoff(struct ahd_softc *ahd, u_int value);
static __inline u_int ahd_get_snscb_qoff(struct ahd_softc *ahd);
static __inline void ahd_set_snscb_qoff(struct ahd_softc *ahd, u_int value);
static __inline u_int ahd_get_sescb_qoff(struct ahd_softc *ahd);
static __inline void ahd_set_sescb_qoff(struct ahd_softc *ahd, u_int value);
static __inline u_int ahd_get_sdscb_qoff(struct ahd_softc *ahd);
static __inline void ahd_set_sdscb_qoff(struct ahd_softc *ahd, u_int value);
static __inline u_int ahd_inb_scbram(struct ahd_softc *ahd, u_int offset);
static __inline u_int ahd_inw_scbram(struct ahd_softc *ahd, u_int offset);
static __inline uint32_t
ahd_inl_scbram(struct ahd_softc *ahd, u_int offset);
static __inline uint64_t
ahd_inq_scbram(struct ahd_softc *ahd, u_int offset);
static __inline void ahd_swap_with_next_hscb(struct ahd_softc *ahd,
struct scb *scb);
static __inline void ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb);
struct ahd_initiator_tinfo *
ahd_fetch_transinfo(struct ahd_softc *ahd,
char channel, u_int our_id,
u_int remote_id,
struct ahd_tmode_tstate **tstate);
uint16_t
ahd_inw(struct ahd_softc *ahd, u_int port);
void ahd_outw(struct ahd_softc *ahd, u_int port,
u_int value);
uint32_t
ahd_inl(struct ahd_softc *ahd, u_int port);
void ahd_outl(struct ahd_softc *ahd, u_int port,
uint32_t value);
uint64_t
ahd_inq(struct ahd_softc *ahd, u_int port);
void ahd_outq(struct ahd_softc *ahd, u_int port,
uint64_t value);
u_int ahd_get_scbptr(struct ahd_softc *ahd);
void ahd_set_scbptr(struct ahd_softc *ahd, u_int scbptr);
u_int ahd_inb_scbram(struct ahd_softc *ahd, u_int offset);
u_int ahd_inw_scbram(struct ahd_softc *ahd, u_int offset);
struct scb *
ahd_lookup_scb(struct ahd_softc *ahd, u_int tag);
void ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb);
static __inline uint8_t *
ahd_get_sense_buf(struct ahd_softc *ahd,
struct scb *scb);
@ -463,25 +148,7 @@ static __inline uint32_t
ahd_get_sense_bufaddr(struct ahd_softc *ahd,
struct scb *scb);
/*
* Return pointers to the transfer negotiation information
* for the specified our_id/remote_id pair.
*/
static __inline struct ahd_initiator_tinfo *
ahd_fetch_transinfo(struct ahd_softc *ahd, char channel, u_int our_id,
u_int remote_id, struct ahd_tmode_tstate **tstate)
{
/*
* Transfer data structures are stored from the perspective
* of the target role. Since the parameters for a connection
* in the initiator role to a given target are the same as
* when the roles are reversed, we pretend we are the target.
*/
if (channel == 'B')
our_id += 8;
*tstate = ahd->enabled_targets[our_id];
return (&(*tstate)->transinfo[remote_id]);
}
#if 0 /* unused */
#define AHD_COPY_COL_IDX(dst, src) \
do { \
@ -489,304 +156,7 @@ do { \
dst->hscb->lun = src->hscb->lun; \
} while (0)
static __inline uint16_t
ahd_inw(struct ahd_softc *ahd, u_int port)
{
/*
* Read high byte first as some registers increment
* or have other side effects when the low byte is
* read.
*/
uint16_t r = ahd_inb(ahd, port+1) << 8;
return r | ahd_inb(ahd, port);
}
static __inline void
ahd_outw(struct ahd_softc *ahd, u_int port, u_int value)
{
/*
* Write low byte first to accomodate registers
* such as PRGMCNT where the order maters.
*/
ahd_outb(ahd, port, value & 0xFF);
ahd_outb(ahd, port+1, (value >> 8) & 0xFF);
}
static __inline uint32_t
ahd_inl(struct ahd_softc *ahd, u_int port)
{
return ((ahd_inb(ahd, port))
| (ahd_inb(ahd, port+1) << 8)
| (ahd_inb(ahd, port+2) << 16)
| (ahd_inb(ahd, port+3) << 24));
}
static __inline void
ahd_outl(struct ahd_softc *ahd, u_int port, uint32_t value)
{
ahd_outb(ahd, port, (value) & 0xFF);
ahd_outb(ahd, port+1, ((value) >> 8) & 0xFF);
ahd_outb(ahd, port+2, ((value) >> 16) & 0xFF);
ahd_outb(ahd, port+3, ((value) >> 24) & 0xFF);
}
static __inline uint64_t
ahd_inq(struct ahd_softc *ahd, u_int port)
{
return ((ahd_inb(ahd, port))
| (ahd_inb(ahd, port+1) << 8)
| (ahd_inb(ahd, port+2) << 16)
| (ahd_inb(ahd, port+3) << 24)
| (((uint64_t)ahd_inb(ahd, port+4)) << 32)
| (((uint64_t)ahd_inb(ahd, port+5)) << 40)
| (((uint64_t)ahd_inb(ahd, port+6)) << 48)
| (((uint64_t)ahd_inb(ahd, port+7)) << 56));
}
static __inline void
ahd_outq(struct ahd_softc *ahd, u_int port, uint64_t value)
{
ahd_outb(ahd, port, value & 0xFF);
ahd_outb(ahd, port+1, (value >> 8) & 0xFF);
ahd_outb(ahd, port+2, (value >> 16) & 0xFF);
ahd_outb(ahd, port+3, (value >> 24) & 0xFF);
ahd_outb(ahd, port+4, (value >> 32) & 0xFF);
ahd_outb(ahd, port+5, (value >> 40) & 0xFF);
ahd_outb(ahd, port+6, (value >> 48) & 0xFF);
ahd_outb(ahd, port+7, (value >> 56) & 0xFF);
}
static __inline u_int
ahd_get_scbptr(struct ahd_softc *ahd)
{
AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
return (ahd_inb(ahd, SCBPTR) | (ahd_inb(ahd, SCBPTR + 1) << 8));
}
static __inline void
ahd_set_scbptr(struct ahd_softc *ahd, u_int scbptr)
{
AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
ahd_outb(ahd, SCBPTR, scbptr & 0xFF);
ahd_outb(ahd, SCBPTR+1, (scbptr >> 8) & 0xFF);
}
static __inline u_int
ahd_get_hnscb_qoff(struct ahd_softc *ahd)
{
return (ahd_inw_atomic(ahd, HNSCB_QOFF));
}
static __inline void
ahd_set_hnscb_qoff(struct ahd_softc *ahd, u_int value)
{
ahd_outw_atomic(ahd, HNSCB_QOFF, value);
}
static __inline u_int
ahd_get_hescb_qoff(struct ahd_softc *ahd)
{
return (ahd_inb(ahd, HESCB_QOFF));
}
static __inline void
ahd_set_hescb_qoff(struct ahd_softc *ahd, u_int value)
{
ahd_outb(ahd, HESCB_QOFF, value);
}
static __inline u_int
ahd_get_snscb_qoff(struct ahd_softc *ahd)
{
u_int oldvalue;
AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
oldvalue = ahd_inw(ahd, SNSCB_QOFF);
ahd_outw(ahd, SNSCB_QOFF, oldvalue);
return (oldvalue);
}
static __inline void
ahd_set_snscb_qoff(struct ahd_softc *ahd, u_int value)
{
AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
ahd_outw(ahd, SNSCB_QOFF, value);
}
static __inline u_int
ahd_get_sescb_qoff(struct ahd_softc *ahd)
{
AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
return (ahd_inb(ahd, SESCB_QOFF));
}
static __inline void
ahd_set_sescb_qoff(struct ahd_softc *ahd, u_int value)
{
AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
ahd_outb(ahd, SESCB_QOFF, value);
}
static __inline u_int
ahd_get_sdscb_qoff(struct ahd_softc *ahd)
{
AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
return (ahd_inb(ahd, SDSCB_QOFF) | (ahd_inb(ahd, SDSCB_QOFF + 1) << 8));
}
static __inline void
ahd_set_sdscb_qoff(struct ahd_softc *ahd, u_int value)
{
AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
ahd_outb(ahd, SDSCB_QOFF, value & 0xFF);
ahd_outb(ahd, SDSCB_QOFF+1, (value >> 8) & 0xFF);
}
static __inline u_int
ahd_inb_scbram(struct ahd_softc *ahd, u_int offset)
{
u_int value;
/*
* Workaround PCI-X Rev A. hardware bug.
* After a host read of SCB memory, the chip
* may become confused into thinking prefetch
* was required. This starts the discard timer
* running and can cause an unexpected discard
* timer interrupt. The work around is to read
* a normal register prior to the exhaustion of
* the discard timer. The mode pointer register
* has no side effects and so serves well for
* this purpose.
*
* Razor #528
*/
value = ahd_inb(ahd, offset);
if ((ahd->bugs & AHD_PCIX_SCBRAM_RD_BUG) != 0)
ahd_inb(ahd, MODE_PTR);
return (value);
}
static __inline u_int
ahd_inw_scbram(struct ahd_softc *ahd, u_int offset)
{
return (ahd_inb_scbram(ahd, offset)
| (ahd_inb_scbram(ahd, offset+1) << 8));
}
static __inline uint32_t
ahd_inl_scbram(struct ahd_softc *ahd, u_int offset)
{
return (ahd_inw_scbram(ahd, offset)
| (ahd_inw_scbram(ahd, offset+2) << 16));
}
static __inline uint64_t
ahd_inq_scbram(struct ahd_softc *ahd, u_int offset)
{
return (ahd_inl_scbram(ahd, offset)
| ((uint64_t)ahd_inl_scbram(ahd, offset+4)) << 32);
}
static __inline struct scb *
ahd_lookup_scb(struct ahd_softc *ahd, u_int tag)
{
struct scb* scb;
if (tag >= AHD_SCB_MAX)
return (NULL);
scb = ahd->scb_data.scbindex[tag];
if (scb != NULL)
ahd_sync_scb(ahd, scb,
BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
return (scb);
}
static __inline void
ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb)
{
struct hardware_scb *q_hscb;
struct map_node *q_hscb_map;
uint32_t saved_hscb_busaddr;
/*
* Our queuing method is a bit tricky. The card
* knows in advance which HSCB (by address) to download,
* and we can't disappoint it. To achieve this, the next
* HSCB to download is saved off in ahd->next_queued_hscb.
* When we are called to queue "an arbitrary scb",
* we copy the contents of the incoming HSCB to the one
* the sequencer knows about, swap HSCB pointers and
* finally assign the SCB to the tag indexed location
* in the scb_array. This makes sure that we can still
* locate the correct SCB by SCB_TAG.
*/
q_hscb = ahd->next_queued_hscb;
q_hscb_map = ahd->next_queued_hscb_map;
saved_hscb_busaddr = q_hscb->hscb_busaddr;
memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb));
q_hscb->hscb_busaddr = saved_hscb_busaddr;
q_hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr;
/* Now swap HSCB pointers. */
ahd->next_queued_hscb = scb->hscb;
ahd->next_queued_hscb_map = scb->hscb_map;
scb->hscb = q_hscb;
scb->hscb_map = q_hscb_map;
/* Now define the mapping from tag to SCB in the scbindex */
ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb;
}
/*
* Tell the sequencer about a new transaction to execute.
*/
static __inline void
ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb)
{
ahd_swap_with_next_hscb(ahd, scb);
if (SCBID_IS_NULL(SCB_GET_TAG(scb)))
panic("Attempt to queue invalid SCB tag %x\n",
SCB_GET_TAG(scb));
/*
* Keep a history of SCBs we've downloaded in the qinfifo.
*/
ahd->qinfifo[AHD_QIN_WRAP(ahd->qinfifonext)] = SCB_GET_TAG(scb);
ahd->qinfifonext++;
if (scb->sg_count != 0)
ahd_setup_data_scb(ahd, scb);
else
ahd_setup_noxfer_scb(ahd, scb);
ahd_setup_scb_common(ahd, scb);
/*
* Make sure our data is consistent from the
* perspective of the adapter.
*/
ahd_sync_scb(ahd, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
#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 %d:0x%x bus addr 0x%x - 0x%x%x/0x%x\n",
ahd_name(ahd),
SCB_GET_TAG(scb), scb->hscb->scsiid,
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 */
ahd_set_hnscb_qoff(ahd, ahd->qinfifonext);
}
static __inline uint8_t *
ahd_get_sense_buf(struct ahd_softc *ahd, struct scb *scb)
@ -801,151 +171,6 @@ ahd_get_sense_bufaddr(struct ahd_softc *ahd, struct scb *scb)
}
/************************** Interrupt Processing ******************************/
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 int ahd_intr(struct ahd_softc *ahd);
static __inline void
ahd_sync_qoutfifo(struct ahd_softc *ahd, int op)
{
ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
/*offset*/0,
/*len*/AHD_SCB_MAX * sizeof(struct ahd_completion), op);
}
static __inline void
ahd_sync_tqinfifo(struct ahd_softc *ahd, int op)
{
#ifdef AHD_TARGET_MODE
if ((ahd->flags & AHD_TARGETROLE) != 0) {
ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
ahd->shared_data_map.dmamap,
ahd_targetcmd_offset(ahd, 0),
sizeof(struct target_cmd) * AHD_TMODE_CMDS,
op);
}
#endif
}
/*
* See if the firmware has posted any completed commands
* into our in-core command complete fifos.
*/
#define AHD_RUN_QOUTFIFO 0x1
#define AHD_RUN_TQINFIFO 0x2
static __inline u_int
ahd_check_cmdcmpltqueues(struct ahd_softc *ahd)
{
u_int retval;
retval = 0;
ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
/*offset*/ahd->qoutfifonext * sizeof(*ahd->qoutfifo),
/*len*/sizeof(*ahd->qoutfifo), BUS_DMASYNC_POSTREAD);
if (ahd->qoutfifo[ahd->qoutfifonext].valid_tag
== ahd->qoutfifonext_valid_tag)
retval |= AHD_RUN_QOUTFIFO;
#ifdef AHD_TARGET_MODE
if ((ahd->flags & AHD_TARGETROLE) != 0
&& (ahd->flags & AHD_TQINFIFO_BLOCKED) == 0) {
ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
ahd->shared_data_map.dmamap,
ahd_targetcmd_offset(ahd, ahd->tqinfifofnext),
/*len*/sizeof(struct target_cmd),
BUS_DMASYNC_POSTREAD);
if (ahd->targetcmds[ahd->tqinfifonext].cmd_valid != 0)
retval |= AHD_RUN_TQINFIFO;
}
#endif
return (retval);
}
/*
* Catch an interrupt from the adapter
*/
static __inline int
ahd_intr(struct ahd_softc *ahd)
{
u_int intstat;
if ((ahd->pause & INTEN) == 0) {
/*
* Our interrupt is not enabled on the chip
* and may be disabled for re-entrancy reasons,
* so just return. This is likely just a shared
* interrupt.
*/
return (0);
}
/*
* Instead of directly reading the interrupt status register,
* infer the cause of the interrupt by checking our in-core
* completion queues. This avoids a costly PCI bus read in
* most cases.
*/
if ((ahd->flags & AHD_ALL_INTERRUPTS) == 0
&& (ahd_check_cmdcmpltqueues(ahd) != 0))
intstat = CMDCMPLT;
else
intstat = ahd_inb(ahd, INTSTAT);
if ((intstat & INT_PEND) == 0)
return (0);
if (intstat & CMDCMPLT) {
ahd_outb(ahd, CLRINT, CLRCMDINT);
/*
* Ensure that the chip sees that we've cleared
* this interrupt before we walk the output fifo.
* Otherwise, we may, due to posted bus writes,
* clear the interrupt after we finish the scan,
* and after the sequencer has added new entries
* and asserted the interrupt again.
*/
if ((ahd->bugs & AHD_INTCOLLISION_BUG) != 0) {
if (ahd_is_paused(ahd)) {
/*
* Potentially lost SEQINT.
* If SEQINTCODE is non-zero,
* simulate the SEQINT.
*/
if (ahd_inb(ahd, SEQINTCODE) != NO_SEQINT)
intstat |= SEQINT;
}
} else {
ahd_flush_device_writes(ahd);
}
ahd_run_qoutfifo(ahd);
ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket]++;
ahd->cmdcmplt_total++;
#ifdef AHD_TARGET_MODE
if ((ahd->flags & AHD_TARGETROLE) != 0)
ahd_run_tqinfifo(ahd, /*paused*/FALSE);
#endif
}
/*
* 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);
} else if ((intstat & (PCIINT|SPLTINT)) != 0) {
ahd->bus_intr(ahd);
} else {
if ((intstat & SEQINT) != 0)
ahd_handle_seqint(ahd, intstat);
if ((intstat & SCSIINT) != 0)
ahd_handle_scsiint(ahd, intstat);
}
return (1);
}
int ahd_intr(struct ahd_softc *ahd);
#endif /* _AIC79XX_INLINE_H_ */

View File

@ -193,7 +193,7 @@ struct ahd_linux_iocell_opts
#define AIC79XX_PRECOMP_INDEX 0
#define AIC79XX_SLEWRATE_INDEX 1
#define AIC79XX_AMPLITUDE_INDEX 2
static struct ahd_linux_iocell_opts aic79xx_iocell_info[] =
static const struct ahd_linux_iocell_opts aic79xx_iocell_info[] =
{
AIC79XX_DEFAULT_IOOPTS,
AIC79XX_DEFAULT_IOOPTS,
@ -369,10 +369,167 @@ static void ahd_release_simq(struct ahd_softc *ahd);
static int ahd_linux_unit;
/****************************** Inlines ***************************************/
static __inline void ahd_linux_unmap_scb(struct ahd_softc*, struct scb*);
/************************** OS Utility Wrappers *******************************/
void ahd_delay(long);
void
ahd_delay(long usec)
{
/*
* udelay on Linux can have problems for
* multi-millisecond waits. Wait at most
* 1024us per call.
*/
while (usec > 0) {
udelay(usec % 1024);
usec -= 1024;
}
}
static __inline void
/***************************** Low Level I/O **********************************/
uint8_t ahd_inb(struct ahd_softc * ahd, long port);
void ahd_outb(struct ahd_softc * ahd, long port, uint8_t val);
void ahd_outw_atomic(struct ahd_softc * ahd,
long port, uint16_t val);
void ahd_outsb(struct ahd_softc * ahd, long port,
uint8_t *, int count);
void ahd_insb(struct ahd_softc * ahd, long port,
uint8_t *, int count);
uint8_t
ahd_inb(struct ahd_softc * ahd, long port)
{
uint8_t x;
if (ahd->tags[0] == BUS_SPACE_MEMIO) {
x = readb(ahd->bshs[0].maddr + port);
} else {
x = inb(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF));
}
mb();
return (x);
}
#if 0 /* unused */
static uint16_t
ahd_inw_atomic(struct ahd_softc * ahd, long port)
{
uint8_t x;
if (ahd->tags[0] == BUS_SPACE_MEMIO) {
x = readw(ahd->bshs[0].maddr + port);
} else {
x = inw(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF));
}
mb();
return (x);
}
#endif
void
ahd_outb(struct ahd_softc * ahd, long port, uint8_t val)
{
if (ahd->tags[0] == BUS_SPACE_MEMIO) {
writeb(val, ahd->bshs[0].maddr + port);
} else {
outb(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF));
}
mb();
}
void
ahd_outw_atomic(struct ahd_softc * ahd, long port, uint16_t val)
{
if (ahd->tags[0] == BUS_SPACE_MEMIO) {
writew(val, ahd->bshs[0].maddr + port);
} else {
outw(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF));
}
mb();
}
void
ahd_outsb(struct ahd_softc * ahd, long port, uint8_t *array, int count)
{
int i;
/*
* There is probably a more efficient way to do this on Linux
* but we don't use this for anything speed critical and this
* should work.
*/
for (i = 0; i < count; i++)
ahd_outb(ahd, port, *array++);
}
void
ahd_insb(struct ahd_softc * ahd, long port, uint8_t *array, int count)
{
int i;
/*
* There is probably a more efficient way to do this on Linux
* but we don't use this for anything speed critical and this
* should work.
*/
for (i = 0; i < count; i++)
*array++ = ahd_inb(ahd, port);
}
/******************************* PCI Routines *********************************/
uint32_t
ahd_pci_read_config(ahd_dev_softc_t pci, int reg, int width)
{
switch (width) {
case 1:
{
uint8_t retval;
pci_read_config_byte(pci, reg, &retval);
return (retval);
}
case 2:
{
uint16_t retval;
pci_read_config_word(pci, reg, &retval);
return (retval);
}
case 4:
{
uint32_t retval;
pci_read_config_dword(pci, reg, &retval);
return (retval);
}
default:
panic("ahd_pci_read_config: Read size too big");
/* NOTREACHED */
return (0);
}
}
void
ahd_pci_write_config(ahd_dev_softc_t pci, int reg, uint32_t value, int width)
{
switch (width) {
case 1:
pci_write_config_byte(pci, reg, value);
break;
case 2:
pci_write_config_word(pci, reg, value);
break;
case 4:
pci_write_config_dword(pci, reg, value);
break;
default:
panic("ahd_pci_write_config: Write size too big");
/* NOTREACHED */
}
}
/****************************** Inlines ***************************************/
static void ahd_linux_unmap_scb(struct ahd_softc*, struct scb*);
static void
ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb)
{
struct scsi_cmnd *cmd;
@ -400,13 +557,11 @@ ahd_linux_info(struct Scsi_Host *host)
bp = &buffer[0];
ahd = *(struct ahd_softc **)host->hostdata;
memset(bp, 0, sizeof(buffer));
strcpy(bp, "Adaptec AIC79XX PCI-X SCSI HBA DRIVER, Rev ");
strcat(bp, AIC79XX_DRIVER_VERSION);
strcat(bp, "\n");
strcat(bp, " <");
strcpy(bp, "Adaptec AIC79XX PCI-X SCSI HBA DRIVER, Rev " AIC79XX_DRIVER_VERSION "\n"
" <");
strcat(bp, ahd->description);
strcat(bp, ">\n");
strcat(bp, " ");
strcat(bp, ">\n"
" ");
ahd_controller_info(ahd, ahd_info);
strcat(bp, ahd_info);
@ -432,7 +587,7 @@ ahd_linux_queue(struct scsi_cmnd * cmd, void (*scsi_done) (struct scsi_cmnd *))
return rtn;
}
static inline struct scsi_target **
static struct scsi_target **
ahd_linux_target_in_softc(struct scsi_target *starget)
{
struct ahd_softc *ahd =
@ -991,7 +1146,7 @@ aic79xx_setup(char *s)
char *p;
char *end;
static struct {
static const struct {
const char *name;
uint32_t *flag;
} options[] = {
@ -1223,7 +1378,7 @@ ahd_platform_init(struct ahd_softc *ahd)
* Lookup and commit any modified IO Cell options.
*/
if (ahd->unit < ARRAY_SIZE(aic79xx_iocell_info)) {
struct ahd_linux_iocell_opts *iocell_opts;
const struct ahd_linux_iocell_opts *iocell_opts;
iocell_opts = &aic79xx_iocell_info[ahd->unit];
if (iocell_opts->precomp != AIC79XX_DEFAULT_PRECOMP)
@ -2613,7 +2768,7 @@ static void ahd_linux_set_pcomp_en(struct scsi_target *starget, int pcomp)
uint8_t precomp;
if (ahd->unit < ARRAY_SIZE(aic79xx_iocell_info)) {
struct ahd_linux_iocell_opts *iocell_opts;
const struct ahd_linux_iocell_opts *iocell_opts;
iocell_opts = &aic79xx_iocell_info[ahd->unit];
precomp = iocell_opts->precomp;

View File

@ -222,22 +222,6 @@ typedef struct timer_list ahd_timer_t;
/***************************** Timer Facilities *******************************/
#define ahd_timer_init init_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, int usec,
ahd_callback_t *func, void *arg);
static __inline void
ahd_timer_reset(ahd_timer_t *timer, int usec, ahd_callback_t *func, void *arg)
{
struct ahd_softc *ahd;
ahd = (struct ahd_softc *)arg;
del_timer(timer);
timer->data = (u_long)arg;
timer->expires = jiffies + (usec * HZ)/1000000;
timer->function = (ahd_linux_callback_t*)func;
add_timer(timer);
}
/***************************** SMP support ************************************/
#include <linux/spinlock.h>
@ -376,7 +360,7 @@ struct ahd_platform_data {
#define AHD_LINUX_NOIRQ ((uint32_t)~0)
uint32_t irq; /* IRQ for this adapter */
uint32_t bios_address;
uint32_t mem_busaddr; /* Mem Base Addr */
resource_size_t mem_busaddr; /* Mem Base Addr */
};
/************************** OS Utility Wrappers *******************************/
@ -386,111 +370,18 @@ struct ahd_platform_data {
#define malloc(size, type, flags) kmalloc(size, flags)
#define free(ptr, type) kfree(ptr)
static __inline void ahd_delay(long);
static __inline void
ahd_delay(long usec)
{
/*
* udelay on Linux can have problems for
* multi-millisecond waits. Wait at most
* 1024us per call.
*/
while (usec > 0) {
udelay(usec % 1024);
usec -= 1024;
}
}
void ahd_delay(long);
/***************************** Low Level I/O **********************************/
static __inline uint8_t ahd_inb(struct ahd_softc * ahd, long port);
static __inline uint16_t ahd_inw_atomic(struct ahd_softc * ahd, long port);
static __inline void ahd_outb(struct ahd_softc * ahd, long port, uint8_t val);
static __inline void ahd_outw_atomic(struct ahd_softc * ahd,
uint8_t ahd_inb(struct ahd_softc * ahd, long port);
void ahd_outb(struct ahd_softc * ahd, long port, uint8_t val);
void ahd_outw_atomic(struct ahd_softc * ahd,
long port, uint16_t val);
static __inline void ahd_outsb(struct ahd_softc * ahd, long port,
void ahd_outsb(struct ahd_softc * ahd, long port,
uint8_t *, int count);
static __inline void ahd_insb(struct ahd_softc * ahd, long port,
void ahd_insb(struct ahd_softc * ahd, long port,
uint8_t *, int count);
static __inline uint8_t
ahd_inb(struct ahd_softc * ahd, long port)
{
uint8_t x;
if (ahd->tags[0] == BUS_SPACE_MEMIO) {
x = readb(ahd->bshs[0].maddr + port);
} else {
x = inb(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF));
}
mb();
return (x);
}
static __inline uint16_t
ahd_inw_atomic(struct ahd_softc * ahd, long port)
{
uint8_t x;
if (ahd->tags[0] == BUS_SPACE_MEMIO) {
x = readw(ahd->bshs[0].maddr + port);
} else {
x = inw(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF));
}
mb();
return (x);
}
static __inline void
ahd_outb(struct ahd_softc * ahd, long port, uint8_t val)
{
if (ahd->tags[0] == BUS_SPACE_MEMIO) {
writeb(val, ahd->bshs[0].maddr + port);
} else {
outb(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF));
}
mb();
}
static __inline void
ahd_outw_atomic(struct ahd_softc * ahd, long port, uint16_t val)
{
if (ahd->tags[0] == BUS_SPACE_MEMIO) {
writew(val, ahd->bshs[0].maddr + port);
} else {
outw(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF));
}
mb();
}
static __inline void
ahd_outsb(struct ahd_softc * ahd, long port, uint8_t *array, int count)
{
int i;
/*
* There is probably a more efficient way to do this on Linux
* but we don't use this for anything speed critical and this
* should work.
*/
for (i = 0; i < count; i++)
ahd_outb(ahd, port, *array++);
}
static __inline void
ahd_insb(struct ahd_softc * ahd, long port, uint8_t *array, int count)
{
int i;
/*
* There is probably a more efficient way to do this on Linux
* but we don't use this for anything speed critical and this
* should work.
*/
for (i = 0; i < count; i++)
*array++ = ahd_inb(ahd, port);
}
/**************************** Initialization **********************************/
int ahd_linux_register_host(struct ahd_softc *,
struct scsi_host_template *);
@ -593,62 +484,12 @@ void ahd_linux_pci_exit(void);
int ahd_pci_map_registers(struct ahd_softc *ahd);
int ahd_pci_map_int(struct ahd_softc *ahd);
static __inline uint32_t ahd_pci_read_config(ahd_dev_softc_t pci,
uint32_t ahd_pci_read_config(ahd_dev_softc_t pci,
int reg, int width);
static __inline uint32_t
ahd_pci_read_config(ahd_dev_softc_t pci, int reg, int width)
{
switch (width) {
case 1:
{
uint8_t retval;
pci_read_config_byte(pci, reg, &retval);
return (retval);
}
case 2:
{
uint16_t retval;
pci_read_config_word(pci, reg, &retval);
return (retval);
}
case 4:
{
uint32_t retval;
pci_read_config_dword(pci, reg, &retval);
return (retval);
}
default:
panic("ahd_pci_read_config: Read size too big");
/* NOTREACHED */
return (0);
}
}
static __inline void ahd_pci_write_config(ahd_dev_softc_t pci,
void ahd_pci_write_config(ahd_dev_softc_t pci,
int reg, uint32_t value,
int width);
static __inline void
ahd_pci_write_config(ahd_dev_softc_t pci, int reg, uint32_t value, int width)
{
switch (width) {
case 1:
pci_write_config_byte(pci, reg, value);
break;
case 2:
pci_write_config_word(pci, reg, value);
break;
case 4:
pci_write_config_dword(pci, reg, value);
break;
default:
panic("ahd_pci_write_config: Write size too big");
/* NOTREACHED */
}
}
static __inline int ahd_get_pci_function(ahd_dev_softc_t);
static __inline int
ahd_get_pci_function(ahd_dev_softc_t pci)

View File

@ -49,7 +49,7 @@
ID2C(x), \
ID2C(IDIROC(x))
static struct pci_device_id ahd_linux_pci_id_table[] = {
static const struct pci_device_id ahd_linux_pci_id_table[] = {
/* aic7901 based controllers */
ID(ID_AHA_29320A),
ID(ID_AHA_29320ALP),
@ -159,7 +159,7 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
char buf[80];
struct ahd_softc *ahd;
ahd_dev_softc_t pci;
struct ahd_pci_identity *entry;
const struct ahd_pci_identity *entry;
char *name;
int error;
struct device *dev = &pdev->dev;
@ -249,8 +249,8 @@ ahd_linux_pci_exit(void)
}
static int
ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd, u_long *base,
u_long *base2)
ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd, resource_size_t *base,
resource_size_t *base2)
{
*base = pci_resource_start(ahd->dev_softc, 0);
/*
@ -272,11 +272,11 @@ ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd, u_long *base,
static int
ahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd,
u_long *bus_addr,
resource_size_t *bus_addr,
uint8_t __iomem **maddr)
{
u_long start;
u_long base_page;
resource_size_t start;
resource_size_t base_page;
u_long base_offset;
int error = 0;
@ -310,7 +310,7 @@ int
ahd_pci_map_registers(struct ahd_softc *ahd)
{
uint32_t command;
u_long base;
resource_size_t base;
uint8_t __iomem *maddr;
int error;
@ -346,31 +346,32 @@ ahd_pci_map_registers(struct ahd_softc *ahd)
} else
command |= PCIM_CMD_MEMEN;
} else if (bootverbose) {
printf("aic79xx: PCI%d:%d:%d MEM region 0x%lx "
printf("aic79xx: PCI%d:%d:%d MEM region 0x%llx "
"unavailable. Cannot memory map device.\n",
ahd_get_pci_bus(ahd->dev_softc),
ahd_get_pci_slot(ahd->dev_softc),
ahd_get_pci_function(ahd->dev_softc),
base);
(unsigned long long)base);
}
if (maddr == NULL) {
u_long base2;
resource_size_t base2;
error = ahd_linux_pci_reserve_io_regions(ahd, &base, &base2);
if (error == 0) {
ahd->tags[0] = BUS_SPACE_PIO;
ahd->tags[1] = BUS_SPACE_PIO;
ahd->bshs[0].ioport = base;
ahd->bshs[1].ioport = base2;
ahd->bshs[0].ioport = (u_long)base;
ahd->bshs[1].ioport = (u_long)base2;
command |= PCIM_CMD_PORTEN;
} else {
printf("aic79xx: PCI%d:%d:%d IO regions 0x%lx and 0x%lx"
"unavailable. Cannot map device.\n",
printf("aic79xx: PCI%d:%d:%d IO regions 0x%llx and "
"0x%llx unavailable. Cannot map device.\n",
ahd_get_pci_bus(ahd->dev_softc),
ahd_get_pci_slot(ahd->dev_softc),
ahd_get_pci_function(ahd->dev_softc),
base, base2);
(unsigned long long)base,
(unsigned long long)base2);
}
}
ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, 4);

View File

@ -97,7 +97,7 @@ static ahd_device_setup_t ahd_aic7901A_setup;
static ahd_device_setup_t ahd_aic7902_setup;
static ahd_device_setup_t ahd_aic790X_setup;
static struct ahd_pci_identity ahd_pci_ident_table [] =
static const struct ahd_pci_identity ahd_pci_ident_table[] =
{
/* aic7901 based controllers */
{
@ -253,7 +253,7 @@ static void ahd_configure_termination(struct ahd_softc *ahd,
static void ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat);
static void ahd_pci_intr(struct ahd_softc *ahd);
struct ahd_pci_identity *
const struct ahd_pci_identity *
ahd_find_pci_device(ahd_dev_softc_t pci)
{
uint64_t full_id;
@ -261,7 +261,7 @@ ahd_find_pci_device(ahd_dev_softc_t pci)
uint16_t vendor;
uint16_t subdevice;
uint16_t subvendor;
struct ahd_pci_identity *entry;
const struct ahd_pci_identity *entry;
u_int i;
vendor = ahd_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2);
@ -292,7 +292,7 @@ ahd_find_pci_device(ahd_dev_softc_t pci)
}
int
ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry)
ahd_pci_config(struct ahd_softc *ahd, const struct ahd_pci_identity *entry)
{
struct scb_data *shared_scb_data;
u_int command;

View File

@ -57,7 +57,7 @@ static int ahd_proc_write_seeprom(struct ahd_softc *ahd,
* Table of syncrates that don't follow the "divisible by 4"
* rule. This table will be expanded in future SCSI specs.
*/
static struct {
static const struct {
u_int period_factor;
u_int period; /* in 100ths of ns */
} scsi_syncrates[] = {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,7 @@
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#120 $
* $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#77 $
*/
static uint8_t seqprog[] = {
static const uint8_t seqprog[] = {
0xff, 0x02, 0x06, 0x78,
0x00, 0xea, 0x6e, 0x59,
0x01, 0xea, 0x04, 0x30,
@ -1027,7 +1027,7 @@ ahd_patch0_func(struct ahd_softc *ahd)
return (0);
}
static struct patch {
static const struct patch {
ahd_patch_func_t *patch_func;
uint32_t begin :10,
skip_instr :10,
@ -1166,7 +1166,7 @@ static struct patch {
{ ahd_patch23_func, 815, 11, 1 }
};
static struct cs {
static const struct cs {
uint16_t begin;
uint16_t end;
} critical_sections[] = {

View File

@ -736,7 +736,7 @@ struct ahc_syncrate {
#define ST_SXFR 0x010 /* Rate Single Transition Only */
#define DT_SXFR 0x040 /* Rate Double Transition Only */
uint8_t period; /* Period to send to SCSI target */
char *rate;
const char *rate;
};
/* Safe and valid period for async negotiations. */
@ -1114,7 +1114,7 @@ typedef int (ahc_device_setup_t)(struct ahc_softc *);
struct ahc_pci_identity {
uint64_t full_id;
uint64_t id_mask;
char *name;
const char *name;
ahc_device_setup_t *setup;
};
@ -1133,15 +1133,11 @@ extern const int ahc_num_aic7770_devs;
/*************************** Function Declarations ****************************/
/******************************************************************************/
u_int ahc_index_busy_tcl(struct ahc_softc *ahc, u_int tcl);
void ahc_unbusy_tcl(struct ahc_softc *ahc, u_int tcl);
void ahc_busy_tcl(struct ahc_softc *ahc,
u_int tcl, u_int busyid);
/***************************** PCI Front End *********************************/
struct ahc_pci_identity *ahc_find_pci_device(ahc_dev_softc_t);
const struct ahc_pci_identity *ahc_find_pci_device(ahc_dev_softc_t);
int ahc_pci_config(struct ahc_softc *,
struct ahc_pci_identity *);
const struct ahc_pci_identity *);
int ahc_pci_test_register_access(struct ahc_softc *);
#ifdef CONFIG_PM
void ahc_pci_resume(struct ahc_softc *ahc);
@ -1155,9 +1151,6 @@ int aic7770_config(struct ahc_softc *ahc,
/************************** SCB and SCB queue management **********************/
int ahc_probe_scbs(struct ahc_softc *);
void ahc_run_untagged_queues(struct ahc_softc *ahc);
void ahc_run_untagged_queue(struct ahc_softc *ahc,
struct scb_tailq *queue);
void ahc_qinfifo_requeue_tail(struct ahc_softc *ahc,
struct scb *scb);
int ahc_match_scb(struct ahc_softc *ahc, struct scb *scb,
@ -1178,22 +1171,8 @@ int ahc_resume(struct ahc_softc *ahc);
#endif
void ahc_set_unit(struct ahc_softc *, int);
void ahc_set_name(struct ahc_softc *, char *);
void ahc_alloc_scbs(struct ahc_softc *ahc);
void ahc_free(struct ahc_softc *ahc);
int ahc_reset(struct ahc_softc *ahc, int reinit);
void ahc_shutdown(void *arg);
/*************************** Interrupt Services *******************************/
void ahc_clear_intstat(struct ahc_softc *ahc);
void ahc_run_qoutfifo(struct ahc_softc *ahc);
#ifdef AHC_TARGET_MODE
void ahc_run_tqinfifo(struct ahc_softc *ahc, int paused);
#endif
void ahc_handle_brkadrint(struct ahc_softc *ahc);
void ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat);
void ahc_handle_scsiint(struct ahc_softc *ahc,
u_int intstat);
void ahc_clear_critical_section(struct ahc_softc *ahc);
/***************************** Error Recovery *********************************/
typedef enum {
@ -1214,36 +1193,19 @@ int ahc_search_disc_list(struct ahc_softc *ahc, int target,
char channel, int lun, u_int tag,
int stop_on_first, int remove,
int save_state);
void ahc_freeze_devq(struct ahc_softc *ahc, struct scb *scb);
int ahc_reset_channel(struct ahc_softc *ahc, char channel,
int initiate_reset);
int ahc_abort_scbs(struct ahc_softc *ahc, int target,
char channel, int lun, u_int tag,
role_t role, uint32_t status);
void ahc_restart(struct ahc_softc *ahc);
void ahc_calc_residual(struct ahc_softc *ahc,
struct scb *scb);
/*************************** Utility Functions ********************************/
struct ahc_phase_table_entry*
ahc_lookup_phase_entry(int phase);
void ahc_compile_devinfo(struct ahc_devinfo *devinfo,
u_int our_id, u_int target,
u_int lun, char channel,
role_t role);
/************************** Transfer Negotiation ******************************/
struct ahc_syncrate* ahc_find_syncrate(struct ahc_softc *ahc, u_int *period,
const struct ahc_syncrate* ahc_find_syncrate(struct ahc_softc *ahc, u_int *period,
u_int *ppr_options, u_int maxsync);
u_int ahc_find_period(struct ahc_softc *ahc,
u_int scsirate, u_int maxsync);
void ahc_validate_offset(struct ahc_softc *ahc,
struct ahc_initiator_tinfo *tinfo,
struct ahc_syncrate *syncrate,
u_int *offset, int wide,
role_t role);
void ahc_validate_width(struct ahc_softc *ahc,
struct ahc_initiator_tinfo *tinfo,
u_int *bus_width,
role_t role);
/*
* Negotiation types. These are used to qualify if we should renegotiate
* even if our goal and current transport parameters are identical.
@ -1263,7 +1225,7 @@ void ahc_set_width(struct ahc_softc *ahc,
u_int width, u_int type, int paused);
void ahc_set_syncrate(struct ahc_softc *ahc,
struct ahc_devinfo *devinfo,
struct ahc_syncrate *syncrate,
const struct ahc_syncrate *syncrate,
u_int period, u_int offset,
u_int ppr_options,
u_int type, int paused);
@ -1305,11 +1267,10 @@ extern uint32_t ahc_debug;
#define AHC_SHOW_MASKED_ERRORS 0x1000
#define AHC_DEBUG_SEQUENCER 0x2000
#endif
void ahc_print_scb(struct scb *scb);
void ahc_print_devinfo(struct ahc_softc *ahc,
struct ahc_devinfo *dev);
void ahc_dump_card_state(struct ahc_softc *ahc);
int ahc_print_register(ahc_reg_parse_entry_t *table,
int ahc_print_register(const ahc_reg_parse_entry_t *table,
u_int num_entries,
const char *name,
u_int address,

View File

@ -238,6 +238,7 @@ register SXFRCTL2 {
register OPTIONMODE {
address 0x008
access_mode RW
count 2
field AUTORATEEN 0x80
field AUTOACKEN 0x40
field ATNMGMNTEN 0x20
@ -254,6 +255,7 @@ register TARGCRCCNT {
address 0x00a
size 2
access_mode RW
count 2
}
/*
@ -344,6 +346,7 @@ register SSTAT2 {
register SSTAT3 {
address 0x00e
access_mode RO
count 2
mask SCSICNT 0xf0
mask OFFCNT 0x0f
mask U2OFFCNT 0x7f
@ -367,6 +370,7 @@ register SCSIID_ULTRA2 {
register SIMODE0 {
address 0x010
access_mode RW
count 2
field ENSELDO 0x40
field ENSELDI 0x20
field ENSELINGO 0x10
@ -429,6 +433,7 @@ register SHADDR {
register SELTIMER {
address 0x018
access_mode RW
count 1
field STAGE6 0x20
field STAGE5 0x10
field STAGE4 0x08
@ -467,6 +472,7 @@ register TARGID {
address 0x01b
size 2
access_mode RW
count 14
}
/*
@ -480,6 +486,7 @@ register TARGID {
register SPIOCAP {
address 0x01b
access_mode RW
count 10
field SOFT1 0x80
field SOFT0 0x40
field SOFTCMDEN 0x20
@ -492,6 +499,7 @@ register SPIOCAP {
register BRDCTL {
address 0x01d
count 11
field BRDDAT7 0x80
field BRDDAT6 0x40
field BRDDAT5 0x20
@ -534,6 +542,7 @@ register BRDCTL {
*/
register SEECTL {
address 0x01e
count 11
field EXTARBACK 0x80
field EXTARBREQ 0x40
field SEEMS 0x20
@ -570,6 +579,7 @@ register SBLKCTL {
register SEQCTL {
address 0x060
access_mode RW
count 15
field PERRORDIS 0x80
field PAUSEDIS 0x40
field FAILDIS 0x20
@ -590,6 +600,7 @@ register SEQCTL {
register SEQRAM {
address 0x061
access_mode RW
count 2
}
/*
@ -604,6 +615,7 @@ register SEQADDR0 {
register SEQADDR1 {
address 0x063
access_mode RW
count 8
mask SEQADDR1_MASK 0x01
}
@ -649,6 +661,7 @@ register NONE {
register FLAGS {
address 0x06b
access_mode RO
count 18
field ZERO 0x02
field CARRY 0x01
}
@ -671,6 +684,7 @@ register FUNCTION1 {
register STACK {
address 0x06f
access_mode RO
count 5
}
const STACK_SIZE 4
@ -692,6 +706,7 @@ register BCTL {
register DSCOMMAND0 {
address 0x084
access_mode RW
count 7
field CACHETHEN 0x80 /* Cache Threshold enable */
field DPARCKEN 0x40 /* Data Parity Check Enable */
field MPARCKEN 0x20 /* Memory Parity Check Enable */
@ -717,6 +732,7 @@ register DSCOMMAND1 {
register BUSTIME {
address 0x085
access_mode RW
count 2
mask BOFF 0xf0
mask BON 0x0f
}
@ -727,6 +743,7 @@ register BUSTIME {
register BUSSPD {
address 0x086
access_mode RW
count 2
mask DFTHRSH 0xc0
mask STBOFF 0x38
mask STBON 0x07
@ -737,6 +754,7 @@ register BUSSPD {
/* aic7850/55/60/70/80/95 only */
register DSPCISTATUS {
address 0x086
count 4
mask DFTHRSH_100 0xc0
}
@ -758,6 +776,7 @@ const SEQ_MAILBOX_SHIFT 0
register HCNTRL {
address 0x087
access_mode RW
count 14
field POWRDN 0x40
field SWINT 0x10
field IRQMS 0x08
@ -869,6 +888,7 @@ register INTSTAT {
register ERROR {
address 0x092
access_mode RO
count 26
field CIOPARERR 0x80 /* Ultra2 only */
field PCIERRSTAT 0x40 /* PCI only */
field MPARERR 0x20 /* PCI only */
@ -885,6 +905,7 @@ register ERROR {
register CLRINT {
address 0x092
access_mode WO
count 24
field CLRPARERR 0x10 /* PCI only */
field CLRBRKADRINT 0x08
field CLRSCSIINT 0x04
@ -943,6 +964,7 @@ register DFDAT {
register SCBCNT {
address 0x09a
access_mode RW
count 1
field SCBAUTO 0x80
mask SCBCNT_MASK 0x1f
}
@ -954,6 +976,7 @@ register SCBCNT {
register QINFIFO {
address 0x09b
access_mode RW
count 12
}
/*
@ -972,11 +995,13 @@ register QINCNT {
register QOUTFIFO {
address 0x09d
access_mode WO
count 7
}
register CRCCONTROL1 {
address 0x09d
access_mode RW
count 3
field CRCONSEEN 0x80
field CRCVALCHKEN 0x40
field CRCENDCHKEN 0x20
@ -1013,6 +1038,7 @@ register SCSIPHASE {
register SFUNCT {
address 0x09f
access_mode RW
count 4
field ALT_MODE 0x80
}
@ -1095,6 +1121,7 @@ scb {
}
SCB_SCSIOFFSET {
size 1
count 1
}
SCB_NEXT {
size 1
@ -1118,6 +1145,7 @@ const SG_SIZEOF 0x08 /* sizeof(struct ahc_dma) */
register SEECTL_2840 {
address 0x0c0
access_mode RW
count 2
field CS_2840 0x04
field CK_2840 0x02
field DO_2840 0x01
@ -1126,6 +1154,7 @@ register SEECTL_2840 {
register STATUS_2840 {
address 0x0c1
access_mode RW
count 4
field EEPROM_TF 0x80
mask BIOS_SEL 0x60
mask ADSEL 0x1e
@ -1161,6 +1190,7 @@ register CCSGCTL {
register CCSCBCNT {
address 0xEF
count 1
}
register CCSCBCTL {
@ -1187,6 +1217,7 @@ register CCSCBRAM {
register SCBBADDR {
address 0x0F0
access_mode RW
count 3
}
register CCSCBPTR {
@ -1195,6 +1226,7 @@ register CCSCBPTR {
register HNSCB_QOFF {
address 0x0F4
count 4
}
register SNSCB_QOFF {
@ -1234,6 +1266,7 @@ register DFF_THRSH {
mask WR_DFTHRSH_85 0x50
mask WR_DFTHRSH_90 0x60
mask WR_DFTHRSH_MAX 0x70
count 4
}
register SG_CACHE_PRE {
@ -1287,6 +1320,7 @@ scratch_ram {
ULTRA_ENB {
alias CMDSIZE_TABLE
size 2
count 2
}
/*
* Bit vector of targets that have disconnection disabled as set by
@ -1296,6 +1330,7 @@ scratch_ram {
*/
DISC_DSB {
size 2
count 6
}
CMDSIZE_TABLE_TAIL {
size 4
@ -1323,6 +1358,7 @@ scratch_ram {
/* Parameters for DMA Logic */
DMAPARAMS {
size 1
count 12
field PRELOADEN 0x80
field WIDEODD 0x40
field SCSIEN 0x20
@ -1436,11 +1472,12 @@ scratch_ram {
KERNEL_TQINPOS {
size 1
}
TQINPOS {
TQINPOS {
size 1
}
ARG_1 {
size 1
count 1
mask SEND_MSG 0x80
mask SEND_SENSE 0x40
mask SEND_REJ 0x20
@ -1495,6 +1532,7 @@ scratch_ram {
size 1
field HA_274_EXTENDED_TRANS 0x01
alias INITIATOR_TAG
count 1
}
SEQ_FLAGS2 {
@ -1518,6 +1556,7 @@ scratch_ram {
*/
SCSICONF {
size 1
count 12
field TERM_ENB 0x80
field RESET_SCSI 0x40
field ENSPCHK 0x20
@ -1527,16 +1566,19 @@ scratch_ram {
INTDEF {
address 0x05c
size 1
count 1
field EDGE_TRIG 0x80
mask VECTOR 0x0f
}
HOSTCONF {
address 0x05d
size 1
count 1
}
HA_274_BIOSCTRL {
address 0x05f
size 1
count 1
mask BIOSMODE 0x30
mask BIOSDISABLED 0x30
field CHANNEL_B_PRIMARY 0x08
@ -1552,6 +1594,7 @@ scratch_ram {
*/
TARG_OFFSET {
size 16
count 1
}
}

View File

@ -84,16 +84,16 @@ struct seeprom_cmd {
};
/* Short opcodes for the c46 */
static struct seeprom_cmd seeprom_ewen = {9, {1, 0, 0, 1, 1, 0, 0, 0, 0}};
static struct seeprom_cmd seeprom_ewds = {9, {1, 0, 0, 0, 0, 0, 0, 0, 0}};
static const struct seeprom_cmd seeprom_ewen = {9, {1, 0, 0, 1, 1, 0, 0, 0, 0}};
static const struct seeprom_cmd seeprom_ewds = {9, {1, 0, 0, 0, 0, 0, 0, 0, 0}};
/* Long opcodes for the C56/C66 */
static struct seeprom_cmd seeprom_long_ewen = {11, {1, 0, 0, 1, 1, 0, 0, 0, 0}};
static struct seeprom_cmd seeprom_long_ewds = {11, {1, 0, 0, 0, 0, 0, 0, 0, 0}};
static const struct seeprom_cmd seeprom_long_ewen = {11, {1, 0, 0, 1, 1, 0, 0, 0, 0}};
static const struct seeprom_cmd seeprom_long_ewds = {11, {1, 0, 0, 0, 0, 0, 0, 0, 0}};
/* Common opcodes */
static struct seeprom_cmd seeprom_write = {3, {1, 0, 1}};
static struct seeprom_cmd seeprom_read = {3, {1, 1, 0}};
static const struct seeprom_cmd seeprom_write = {3, {1, 0, 1}};
static const struct seeprom_cmd seeprom_read = {3, {1, 1, 0}};
/*
* Wait for the SEERDY to go high; about 800 ns.
@ -108,7 +108,7 @@ static struct seeprom_cmd seeprom_read = {3, {1, 1, 0}};
* Send a START condition and the given command
*/
static void
send_seeprom_cmd(struct seeprom_descriptor *sd, struct seeprom_cmd *cmd)
send_seeprom_cmd(struct seeprom_descriptor *sd, const struct seeprom_cmd *cmd)
{
uint8_t temp;
int i = 0;
@ -227,7 +227,7 @@ int
ahc_write_seeprom(struct seeprom_descriptor *sd, uint16_t *buf,
u_int start_addr, u_int count)
{
struct seeprom_cmd *ewen, *ewds;
const struct seeprom_cmd *ewen, *ewds;
uint16_t v;
uint8_t temp;
int i, k;

View File

@ -51,8 +51,7 @@
#endif
/***************************** Lookup Tables **********************************/
char *ahc_chip_names[] =
{
static const char *const ahc_chip_names[] = {
"NONE",
"aic7770",
"aic7850",
@ -75,10 +74,10 @@ static const u_int num_chip_names = ARRAY_SIZE(ahc_chip_names);
*/
struct ahc_hard_error_entry {
uint8_t errno;
char *errmesg;
const char *errmesg;
};
static struct ahc_hard_error_entry ahc_hard_errors[] = {
static const struct ahc_hard_error_entry ahc_hard_errors[] = {
{ ILLHADDR, "Illegal Host Access" },
{ ILLSADDR, "Illegal Sequencer Address referrenced" },
{ ILLOPCODE, "Illegal Opcode in sequencer program" },
@ -90,7 +89,7 @@ static struct ahc_hard_error_entry ahc_hard_errors[] = {
};
static const u_int num_errors = ARRAY_SIZE(ahc_hard_errors);
static struct ahc_phase_table_entry ahc_phase_table[] =
static const struct ahc_phase_table_entry ahc_phase_table[] =
{
{ P_DATAOUT, MSG_NOOP, "in Data-out phase" },
{ P_DATAIN, MSG_INITIATOR_DET_ERR, "in Data-in phase" },
@ -115,7 +114,7 @@ static const u_int num_phases = ARRAY_SIZE(ahc_phase_table) - 1;
* Provides a mapping of tranfer periods in ns to the proper value to
* stick in the scsixfer reg.
*/
static struct ahc_syncrate ahc_syncrates[] =
static const struct ahc_syncrate ahc_syncrates[] =
{
/* ultra2 fast/ultra period rate */
{ 0x42, 0x000, 9, "80.0" },
@ -148,7 +147,7 @@ static struct ahc_tmode_tstate*
static void ahc_free_tstate(struct ahc_softc *ahc,
u_int scsi_id, char channel, int force);
#endif
static struct ahc_syncrate*
static const struct ahc_syncrate*
ahc_devlimited_syncrate(struct ahc_softc *ahc,
struct ahc_initiator_tinfo *,
u_int *period,
@ -204,9 +203,9 @@ static void ahc_setup_target_msgin(struct ahc_softc *ahc,
#endif
static bus_dmamap_callback_t ahc_dmamap_cb;
static void ahc_build_free_scb_list(struct ahc_softc *ahc);
static int ahc_init_scbdata(struct ahc_softc *ahc);
static void ahc_fini_scbdata(struct ahc_softc *ahc);
static void ahc_build_free_scb_list(struct ahc_softc *ahc);
static int ahc_init_scbdata(struct ahc_softc *ahc);
static void ahc_fini_scbdata(struct ahc_softc *ahc);
static void ahc_qinfifo_requeue(struct ahc_softc *ahc,
struct scb *prev_scb,
struct scb *scb);
@ -222,7 +221,7 @@ static void ahc_dumpseq(struct ahc_softc *ahc);
#endif
static int ahc_loadseq(struct ahc_softc *ahc);
static int ahc_check_patch(struct ahc_softc *ahc,
struct patch **start_patch,
const struct patch **start_patch,
u_int start_instr, u_int *skip_addr);
static void ahc_download_instr(struct ahc_softc *ahc,
u_int instrptr, uint8_t *dconsts);
@ -237,11 +236,582 @@ static void ahc_update_scsiid(struct ahc_softc *ahc,
static int ahc_handle_target_cmd(struct ahc_softc *ahc,
struct target_cmd *cmd);
#endif
static u_int ahc_index_busy_tcl(struct ahc_softc *ahc, u_int tcl);
static void ahc_unbusy_tcl(struct ahc_softc *ahc, u_int tcl);
static void ahc_busy_tcl(struct ahc_softc *ahc,
u_int tcl, u_int busyid);
/************************** SCB and SCB queue management **********************/
static void ahc_run_untagged_queues(struct ahc_softc *ahc);
static void ahc_run_untagged_queue(struct ahc_softc *ahc,
struct scb_tailq *queue);
/****************************** Initialization ********************************/
static void ahc_alloc_scbs(struct ahc_softc *ahc);
static void ahc_shutdown(void *arg);
/*************************** Interrupt Services *******************************/
static void ahc_clear_intstat(struct ahc_softc *ahc);
static void ahc_run_qoutfifo(struct ahc_softc *ahc);
#ifdef AHC_TARGET_MODE
static void ahc_run_tqinfifo(struct ahc_softc *ahc, int paused);
#endif
static void ahc_handle_brkadrint(struct ahc_softc *ahc);
static void ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat);
static void ahc_handle_scsiint(struct ahc_softc *ahc,
u_int intstat);
static void ahc_clear_critical_section(struct ahc_softc *ahc);
/***************************** Error Recovery *********************************/
static void ahc_freeze_devq(struct ahc_softc *ahc, struct scb *scb);
static int ahc_abort_scbs(struct ahc_softc *ahc, int target,
char channel, int lun, u_int tag,
role_t role, uint32_t status);
static void ahc_calc_residual(struct ahc_softc *ahc,
struct scb *scb);
/*********************** Untagged Transaction Routines ************************/
static inline void ahc_freeze_untagged_queues(struct ahc_softc *ahc);
static inline void ahc_release_untagged_queues(struct ahc_softc *ahc);
/*
* Block our completion routine from starting the next untagged
* transaction for this target or target lun.
*/
static inline void
ahc_freeze_untagged_queues(struct ahc_softc *ahc)
{
if ((ahc->flags & AHC_SCB_BTT) == 0)
ahc->untagged_queue_lock++;
}
/*
* Allow the next untagged transaction for this target or target lun
* to be executed. We use a counting semaphore to allow the lock
* to be acquired recursively. Once the count drops to zero, the
* transaction queues will be run.
*/
static inline void
ahc_release_untagged_queues(struct ahc_softc *ahc)
{
if ((ahc->flags & AHC_SCB_BTT) == 0) {
ahc->untagged_queue_lock--;
if (ahc->untagged_queue_lock == 0)
ahc_run_untagged_queues(ahc);
}
}
/************************* Sequencer Execution Control ************************/
/*
* Work around any chip bugs related to halting sequencer execution.
* On Ultra2 controllers, we must clear the CIOBUS stretch signal by
* reading a register that will set this signal and deassert it.
* Without this workaround, if the chip is paused, by an interrupt or
* manual pause while accessing scb ram, accesses to certain registers
* will hang the system (infinite pci retries).
*/
static void
ahc_pause_bug_fix(struct ahc_softc *ahc)
{
if ((ahc->features & AHC_ULTRA2) != 0)
(void)ahc_inb(ahc, CCSCBCTL);
}
/*
* Determine whether the sequencer has halted code execution.
* Returns non-zero status if the sequencer is stopped.
*/
int
ahc_is_paused(struct ahc_softc *ahc)
{
return ((ahc_inb(ahc, HCNTRL) & PAUSE) != 0);
}
/*
* Request that the sequencer stop and wait, indefinitely, for it
* to stop. The sequencer will only acknowledge that it is paused
* once it has reached an instruction boundary and PAUSEDIS is
* cleared in the SEQCTL register. The sequencer may use PAUSEDIS
* for critical sections.
*/
void
ahc_pause(struct ahc_softc *ahc)
{
ahc_outb(ahc, HCNTRL, ahc->pause);
/*
* Since the sequencer can disable pausing in a critical section, we
* must loop until it actually stops.
*/
while (ahc_is_paused(ahc) == 0)
;
ahc_pause_bug_fix(ahc);
}
/*
* Allow the sequencer to continue program execution.
* We check here to ensure that no additional interrupt
* sources that would cause the sequencer to halt have been
* asserted. If, for example, a SCSI bus reset is detected
* while we are fielding a different, pausing, interrupt type,
* we don't want to release the sequencer before going back
* into our interrupt handler and dealing with this new
* condition.
*/
void
ahc_unpause(struct ahc_softc *ahc)
{
if ((ahc_inb(ahc, INTSTAT) & (SCSIINT | SEQINT | BRKADRINT)) == 0)
ahc_outb(ahc, HCNTRL, ahc->unpause);
}
/************************** Memory mapping routines ***************************/
static struct ahc_dma_seg *
ahc_sg_bus_to_virt(struct scb *scb, uint32_t sg_busaddr)
{
int sg_index;
sg_index = (sg_busaddr - scb->sg_list_phys)/sizeof(struct ahc_dma_seg);
/* sg_list_phys points to entry 1, not 0 */
sg_index++;
return (&scb->sg_list[sg_index]);
}
static uint32_t
ahc_sg_virt_to_bus(struct scb *scb, struct ahc_dma_seg *sg)
{
int sg_index;
/* sg_list_phys points to entry 1, not 0 */
sg_index = sg - &scb->sg_list[1];
return (scb->sg_list_phys + (sg_index * sizeof(*scb->sg_list)));
}
static uint32_t
ahc_hscb_busaddr(struct ahc_softc *ahc, u_int index)
{
return (ahc->scb_data->hscb_busaddr
+ (sizeof(struct hardware_scb) * index));
}
static void
ahc_sync_scb(struct ahc_softc *ahc, struct scb *scb, int op)
{
ahc_dmamap_sync(ahc, ahc->scb_data->hscb_dmat,
ahc->scb_data->hscb_dmamap,
/*offset*/(scb->hscb - ahc->hscbs) * sizeof(*scb->hscb),
/*len*/sizeof(*scb->hscb), op);
}
void
ahc_sync_sglist(struct ahc_softc *ahc, struct scb *scb, int op)
{
if (scb->sg_count == 0)
return;
ahc_dmamap_sync(ahc, ahc->scb_data->sg_dmat, scb->sg_map->sg_dmamap,
/*offset*/(scb->sg_list - scb->sg_map->sg_vaddr)
* sizeof(struct ahc_dma_seg),
/*len*/sizeof(struct ahc_dma_seg) * scb->sg_count, op);
}
#ifdef AHC_TARGET_MODE
static uint32_t
ahc_targetcmd_offset(struct ahc_softc *ahc, u_int index)
{
return (((uint8_t *)&ahc->targetcmds[index]) - ahc->qoutfifo);
}
#endif
/*********************** Miscelaneous Support Functions ***********************/
/*
* Determine whether the sequencer reported a residual
* for this SCB/transaction.
*/
static void
ahc_update_residual(struct ahc_softc *ahc, struct scb *scb)
{
uint32_t sgptr;
sgptr = ahc_le32toh(scb->hscb->sgptr);
if ((sgptr & SG_RESID_VALID) != 0)
ahc_calc_residual(ahc, scb);
}
/*
* Return pointers to the transfer negotiation information
* for the specified our_id/remote_id pair.
*/
struct ahc_initiator_tinfo *
ahc_fetch_transinfo(struct ahc_softc *ahc, char channel, u_int our_id,
u_int remote_id, struct ahc_tmode_tstate **tstate)
{
/*
* Transfer data structures are stored from the perspective
* of the target role. Since the parameters for a connection
* in the initiator role to a given target are the same as
* when the roles are reversed, we pretend we are the target.
*/
if (channel == 'B')
our_id += 8;
*tstate = ahc->enabled_targets[our_id];
return (&(*tstate)->transinfo[remote_id]);
}
uint16_t
ahc_inw(struct ahc_softc *ahc, u_int port)
{
uint16_t r = ahc_inb(ahc, port+1) << 8;
return r | ahc_inb(ahc, port);
}
void
ahc_outw(struct ahc_softc *ahc, u_int port, u_int value)
{
ahc_outb(ahc, port, value & 0xFF);
ahc_outb(ahc, port+1, (value >> 8) & 0xFF);
}
uint32_t
ahc_inl(struct ahc_softc *ahc, u_int port)
{
return ((ahc_inb(ahc, port))
| (ahc_inb(ahc, port+1) << 8)
| (ahc_inb(ahc, port+2) << 16)
| (ahc_inb(ahc, port+3) << 24));
}
void
ahc_outl(struct ahc_softc *ahc, u_int port, uint32_t value)
{
ahc_outb(ahc, port, (value) & 0xFF);
ahc_outb(ahc, port+1, ((value) >> 8) & 0xFF);
ahc_outb(ahc, port+2, ((value) >> 16) & 0xFF);
ahc_outb(ahc, port+3, ((value) >> 24) & 0xFF);
}
uint64_t
ahc_inq(struct ahc_softc *ahc, u_int port)
{
return ((ahc_inb(ahc, port))
| (ahc_inb(ahc, port+1) << 8)
| (ahc_inb(ahc, port+2) << 16)
| (ahc_inb(ahc, port+3) << 24)
| (((uint64_t)ahc_inb(ahc, port+4)) << 32)
| (((uint64_t)ahc_inb(ahc, port+5)) << 40)
| (((uint64_t)ahc_inb(ahc, port+6)) << 48)
| (((uint64_t)ahc_inb(ahc, port+7)) << 56));
}
void
ahc_outq(struct ahc_softc *ahc, u_int port, uint64_t value)
{
ahc_outb(ahc, port, value & 0xFF);
ahc_outb(ahc, port+1, (value >> 8) & 0xFF);
ahc_outb(ahc, port+2, (value >> 16) & 0xFF);
ahc_outb(ahc, port+3, (value >> 24) & 0xFF);
ahc_outb(ahc, port+4, (value >> 32) & 0xFF);
ahc_outb(ahc, port+5, (value >> 40) & 0xFF);
ahc_outb(ahc, port+6, (value >> 48) & 0xFF);
ahc_outb(ahc, port+7, (value >> 56) & 0xFF);
}
/*
* Get a free scb. If there are none, see if we can allocate a new SCB.
*/
struct scb *
ahc_get_scb(struct ahc_softc *ahc)
{
struct scb *scb;
if ((scb = SLIST_FIRST(&ahc->scb_data->free_scbs)) == NULL) {
ahc_alloc_scbs(ahc);
scb = SLIST_FIRST(&ahc->scb_data->free_scbs);
if (scb == NULL)
return (NULL);
}
SLIST_REMOVE_HEAD(&ahc->scb_data->free_scbs, links.sle);
return (scb);
}
/*
* Return an SCB resource to the free list.
*/
void
ahc_free_scb(struct ahc_softc *ahc, struct scb *scb)
{
struct hardware_scb *hscb;
hscb = scb->hscb;
/* Clean up for the next user */
ahc->scb_data->scbindex[hscb->tag] = NULL;
scb->flags = SCB_FREE;
hscb->control = 0;
SLIST_INSERT_HEAD(&ahc->scb_data->free_scbs, scb, links.sle);
/* Notify the OSM that a resource is now available. */
ahc_platform_scb_free(ahc, scb);
}
struct scb *
ahc_lookup_scb(struct ahc_softc *ahc, u_int tag)
{
struct scb* scb;
scb = ahc->scb_data->scbindex[tag];
if (scb != NULL)
ahc_sync_scb(ahc, scb,
BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
return (scb);
}
static void
ahc_swap_with_next_hscb(struct ahc_softc *ahc, struct scb *scb)
{
struct hardware_scb *q_hscb;
u_int saved_tag;
/*
* Our queuing method is a bit tricky. The card
* knows in advance which HSCB to download, and we
* can't disappoint it. To achieve this, the next
* SCB to download is saved off in ahc->next_queued_scb.
* When we are called to queue "an arbitrary scb",
* we copy the contents of the incoming HSCB to the one
* the sequencer knows about, swap HSCB pointers and
* finally assign the SCB to the tag indexed location
* in the scb_array. This makes sure that we can still
* locate the correct SCB by SCB_TAG.
*/
q_hscb = ahc->next_queued_scb->hscb;
saved_tag = q_hscb->tag;
memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb));
if ((scb->flags & SCB_CDB32_PTR) != 0) {
q_hscb->shared_data.cdb_ptr =
ahc_htole32(ahc_hscb_busaddr(ahc, q_hscb->tag)
+ offsetof(struct hardware_scb, cdb32));
}
q_hscb->tag = saved_tag;
q_hscb->next = scb->hscb->tag;
/* Now swap HSCB pointers. */
ahc->next_queued_scb->hscb = scb->hscb;
scb->hscb = q_hscb;
/* Now define the mapping from tag to SCB in the scbindex */
ahc->scb_data->scbindex[scb->hscb->tag] = scb;
}
/*
* Tell the sequencer about a new transaction to execute.
*/
void
ahc_queue_scb(struct ahc_softc *ahc, struct scb *scb)
{
ahc_swap_with_next_hscb(ahc, scb);
if (scb->hscb->tag == SCB_LIST_NULL
|| scb->hscb->next == SCB_LIST_NULL)
panic("Attempt to queue invalid SCB tag %x:%x\n",
scb->hscb->tag, scb->hscb->next);
/*
* Setup data "oddness".
*/
scb->hscb->lun &= LID;
if (ahc_get_transfer_length(scb) & 0x1)
scb->hscb->lun |= SCB_XFERLEN_ODD;
/*
* Keep a history of SCBs we've downloaded in the qinfifo.
*/
ahc->qinfifo[ahc->qinfifonext++] = scb->hscb->tag;
/*
* Make sure our data is consistent from the
* perspective of the adapter.
*/
ahc_sync_scb(ahc, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
/* Tell the adapter about the newly queued SCB */
if ((ahc->features & AHC_QUEUE_REGS) != 0) {
ahc_outb(ahc, HNSCB_QOFF, ahc->qinfifonext);
} else {
if ((ahc->features & AHC_AUTOPAUSE) == 0)
ahc_pause(ahc);
ahc_outb(ahc, KERNEL_QINPOS, ahc->qinfifonext);
if ((ahc->features & AHC_AUTOPAUSE) == 0)
ahc_unpause(ahc);
}
}
struct scsi_sense_data *
ahc_get_sense_buf(struct ahc_softc *ahc, struct scb *scb)
{
int offset;
offset = scb - ahc->scb_data->scbarray;
return (&ahc->scb_data->sense[offset]);
}
static uint32_t
ahc_get_sense_bufaddr(struct ahc_softc *ahc, struct scb *scb)
{
int offset;
offset = scb - ahc->scb_data->scbarray;
return (ahc->scb_data->sense_busaddr
+ (offset * sizeof(struct scsi_sense_data)));
}
/************************** Interrupt Processing ******************************/
static void
ahc_sync_qoutfifo(struct ahc_softc *ahc, int op)
{
ahc_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap,
/*offset*/0, /*len*/256, op);
}
static void
ahc_sync_tqinfifo(struct ahc_softc *ahc, int op)
{
#ifdef AHC_TARGET_MODE
if ((ahc->flags & AHC_TARGETROLE) != 0) {
ahc_dmamap_sync(ahc, ahc->shared_data_dmat,
ahc->shared_data_dmamap,
ahc_targetcmd_offset(ahc, 0),
sizeof(struct target_cmd) * AHC_TMODE_CMDS,
op);
}
#endif
}
/*
* See if the firmware has posted any completed commands
* into our in-core command complete fifos.
*/
#define AHC_RUN_QOUTFIFO 0x1
#define AHC_RUN_TQINFIFO 0x2
static u_int
ahc_check_cmdcmpltqueues(struct ahc_softc *ahc)
{
u_int retval;
retval = 0;
ahc_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap,
/*offset*/ahc->qoutfifonext, /*len*/1,
BUS_DMASYNC_POSTREAD);
if (ahc->qoutfifo[ahc->qoutfifonext] != SCB_LIST_NULL)
retval |= AHC_RUN_QOUTFIFO;
#ifdef AHC_TARGET_MODE
if ((ahc->flags & AHC_TARGETROLE) != 0
&& (ahc->flags & AHC_TQINFIFO_BLOCKED) == 0) {
ahc_dmamap_sync(ahc, ahc->shared_data_dmat,
ahc->shared_data_dmamap,
ahc_targetcmd_offset(ahc, ahc->tqinfifofnext),
/*len*/sizeof(struct target_cmd),
BUS_DMASYNC_POSTREAD);
if (ahc->targetcmds[ahc->tqinfifonext].cmd_valid != 0)
retval |= AHC_RUN_TQINFIFO;
}
#endif
return (retval);
}
/*
* Catch an interrupt from the adapter
*/
int
ahc_intr(struct ahc_softc *ahc)
{
u_int intstat;
if ((ahc->pause & INTEN) == 0) {
/*
* Our interrupt is not enabled on the chip
* and may be disabled for re-entrancy reasons,
* so just return. This is likely just a shared
* interrupt.
*/
return (0);
}
/*
* Instead of directly reading the interrupt status register,
* infer the cause of the interrupt by checking our in-core
* completion queues. This avoids a costly PCI bus read in
* most cases.
*/
if ((ahc->flags & (AHC_ALL_INTERRUPTS|AHC_EDGE_INTERRUPT)) == 0
&& (ahc_check_cmdcmpltqueues(ahc) != 0))
intstat = CMDCMPLT;
else {
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);
/*
* Ensure that the chip sees that we've cleared
* this interrupt before we walk the output fifo.
* Otherwise, we may, due to posted bus writes,
* clear the interrupt after we finish the scan,
* and after the sequencer has added new entries
* and asserted the interrupt again.
*/
ahc_flush_device_writes(ahc);
ahc_run_qoutfifo(ahc);
#ifdef AHC_TARGET_MODE
if ((ahc->flags & AHC_TARGETROLE) != 0)
ahc_run_tqinfifo(ahc, /*paused*/FALSE);
#endif
}
/*
* 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);
} else if ((intstat & (SEQINT|SCSIINT)) != 0) {
ahc_pause_bug_fix(ahc);
if ((intstat & SEQINT) != 0)
ahc_handle_seqint(ahc, intstat);
if ((intstat & SCSIINT) != 0)
ahc_handle_scsiint(ahc, intstat);
}
return (1);
}
/************************* Sequencer Execution Control ************************/
/*
* Restart the sequencer program from address zero
*/
void
static void
ahc_restart(struct ahc_softc *ahc)
{
@ -302,7 +872,7 @@ ahc_restart(struct ahc_softc *ahc)
}
/************************* Input/Output Queues ********************************/
void
static void
ahc_run_qoutfifo(struct ahc_softc *ahc)
{
struct scb *scb;
@ -349,7 +919,7 @@ ahc_run_qoutfifo(struct ahc_softc *ahc)
}
}
void
static void
ahc_run_untagged_queues(struct ahc_softc *ahc)
{
int i;
@ -358,7 +928,7 @@ ahc_run_untagged_queues(struct ahc_softc *ahc)
ahc_run_untagged_queue(ahc, &ahc->untagged_queues[i]);
}
void
static void
ahc_run_untagged_queue(struct ahc_softc *ahc, struct scb_tailq *queue)
{
struct scb *scb;
@ -374,7 +944,7 @@ ahc_run_untagged_queue(struct ahc_softc *ahc, struct scb_tailq *queue)
}
/************************* Interrupt Handling *********************************/
void
static void
ahc_handle_brkadrint(struct ahc_softc *ahc)
{
/*
@ -403,7 +973,7 @@ ahc_handle_brkadrint(struct ahc_softc *ahc)
ahc_shutdown(ahc);
}
void
static void
ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
{
struct scb *scb;
@ -954,7 +1524,7 @@ unpause:
ahc_unpause(ahc);
}
void
static void
ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
{
u_int scb_index;
@ -1407,7 +1977,7 @@ ahc_force_renegotiation(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
}
#define AHC_MAX_STEPS 2000
void
static void
ahc_clear_critical_section(struct ahc_softc *ahc)
{
int stepping;
@ -1500,7 +2070,7 @@ ahc_clear_critical_section(struct ahc_softc *ahc)
/*
* Clear any pending interrupt status.
*/
void
static void
ahc_clear_intstat(struct ahc_softc *ahc)
{
/* Clear any interrupt conditions this may have caused */
@ -1519,7 +2089,8 @@ ahc_clear_intstat(struct ahc_softc *ahc)
uint32_t ahc_debug = AHC_DEBUG_OPTS;
#endif
void
#if 0 /* unused */
static void
ahc_print_scb(struct scb *scb)
{
int i;
@ -1551,6 +2122,7 @@ ahc_print_scb(struct scb *scb)
}
}
}
#endif
/************************* Transfer Negotiation *******************************/
/*
@ -1634,7 +2206,7 @@ ahc_free_tstate(struct ahc_softc *ahc, u_int scsi_id, char channel, int force)
* by the capabilities of the bus connectivity of and sync settings for
* the target.
*/
struct ahc_syncrate *
const struct ahc_syncrate *
ahc_devlimited_syncrate(struct ahc_softc *ahc,
struct ahc_initiator_tinfo *tinfo,
u_int *period, u_int *ppr_options, role_t role)
@ -1689,11 +2261,11 @@ ahc_devlimited_syncrate(struct ahc_softc *ahc,
* Return the period and offset that should be sent to the target
* if this was the beginning of an SDTR.
*/
struct ahc_syncrate *
const struct ahc_syncrate *
ahc_find_syncrate(struct ahc_softc *ahc, u_int *period,
u_int *ppr_options, u_int maxsync)
{
struct ahc_syncrate *syncrate;
const struct ahc_syncrate *syncrate;
if ((ahc->features & AHC_DT) == 0)
*ppr_options &= ~MSG_EXT_PPR_DT_REQ;
@ -1768,7 +2340,7 @@ ahc_find_syncrate(struct ahc_softc *ahc, u_int *period,
u_int
ahc_find_period(struct ahc_softc *ahc, u_int scsirate, u_int maxsync)
{
struct ahc_syncrate *syncrate;
const struct ahc_syncrate *syncrate;
if ((ahc->features & AHC_ULTRA2) != 0)
scsirate &= SXFR_ULTRA2;
@ -1806,10 +2378,10 @@ ahc_find_period(struct ahc_softc *ahc, u_int scsirate, u_int maxsync)
* Truncate the given synchronous offset to a value the
* current adapter type and syncrate are capable of.
*/
void
static void
ahc_validate_offset(struct ahc_softc *ahc,
struct ahc_initiator_tinfo *tinfo,
struct ahc_syncrate *syncrate,
const struct ahc_syncrate *syncrate,
u_int *offset, int wide, role_t role)
{
u_int maxoffset;
@ -1838,7 +2410,7 @@ ahc_validate_offset(struct ahc_softc *ahc,
* Truncate the given transfer width parameter to a value the
* current adapter type is capable of.
*/
void
static void
ahc_validate_width(struct ahc_softc *ahc, struct ahc_initiator_tinfo *tinfo,
u_int *bus_width, role_t role)
{
@ -1913,7 +2485,7 @@ ahc_update_neg_request(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
*/
void
ahc_set_syncrate(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
struct ahc_syncrate *syncrate, u_int period,
const struct ahc_syncrate *syncrate, u_int period,
u_int offset, u_int ppr_options, u_int type, int paused)
{
struct ahc_initiator_tinfo *tinfo;
@ -2220,11 +2792,11 @@ ahc_fetch_devinfo(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
role);
}
struct ahc_phase_table_entry*
static const struct ahc_phase_table_entry*
ahc_lookup_phase_entry(int phase)
{
struct ahc_phase_table_entry *entry;
struct ahc_phase_table_entry *last_entry;
const struct ahc_phase_table_entry *entry;
const struct ahc_phase_table_entry *last_entry;
/*
* num_phases doesn't include the default entry which
@ -2390,7 +2962,7 @@ ahc_build_transfer_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
*/
struct ahc_initiator_tinfo *tinfo;
struct ahc_tmode_tstate *tstate;
struct ahc_syncrate *rate;
const struct ahc_syncrate *rate;
int dowide;
int dosync;
int doppr;
@ -2655,7 +3227,7 @@ proto_violation_reset:
*/
static void
ahc_handle_message_phase(struct ahc_softc *ahc)
{
{
struct ahc_devinfo devinfo;
u_int bus_phase;
int end_session;
@ -3056,7 +3628,7 @@ ahc_parse_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
switch (ahc->msgin_buf[2]) {
case MSG_EXT_SDTR:
{
struct ahc_syncrate *syncrate;
const struct ahc_syncrate *syncrate;
u_int period;
u_int ppr_options;
u_int offset;
@ -3231,7 +3803,7 @@ ahc_parse_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
}
case MSG_EXT_PPR:
{
struct ahc_syncrate *syncrate;
const struct ahc_syncrate *syncrate;
u_int period;
u_int offset;
u_int bus_width;
@ -3984,7 +4556,7 @@ ahc_free(struct ahc_softc *ahc)
return;
}
void
static void
ahc_shutdown(void *arg)
{
struct ahc_softc *ahc;
@ -4388,7 +4960,7 @@ ahc_fini_scbdata(struct ahc_softc *ahc)
free(scb_data->scbarray, M_DEVBUF);
}
void
static void
ahc_alloc_scbs(struct ahc_softc *ahc)
{
struct scb_data *scb_data;
@ -5121,7 +5693,7 @@ ahc_resume(struct ahc_softc *ahc)
* Return the untagged transaction id for a given target/channel lun.
* Optionally, clear the entry.
*/
u_int
static u_int
ahc_index_busy_tcl(struct ahc_softc *ahc, u_int tcl)
{
u_int scbid;
@ -5142,7 +5714,7 @@ ahc_index_busy_tcl(struct ahc_softc *ahc, u_int tcl)
return (scbid);
}
void
static void
ahc_unbusy_tcl(struct ahc_softc *ahc, u_int tcl)
{
u_int target_offset;
@ -5160,7 +5732,7 @@ ahc_unbusy_tcl(struct ahc_softc *ahc, u_int tcl)
}
}
void
static void
ahc_busy_tcl(struct ahc_softc *ahc, u_int tcl, u_int scbid)
{
u_int target_offset;
@ -5215,7 +5787,7 @@ ahc_match_scb(struct ahc_softc *ahc, struct scb *scb, int target,
return match;
}
void
static void
ahc_freeze_devq(struct ahc_softc *ahc, struct scb *scb)
{
int target;
@ -5707,7 +6279,7 @@ ahc_add_curscb_to_free_list(struct ahc_softc *ahc)
*/
static u_int
ahc_rem_wscb(struct ahc_softc *ahc, u_int scbpos, u_int prev)
{
{
u_int curscb, next;
/*
@ -5756,7 +6328,7 @@ ahc_rem_wscb(struct ahc_softc *ahc, u_int scbpos, u_int prev)
* been modified from CAM_REQ_INPROG. This routine assumes that the sequencer
* is paused before it is called.
*/
int
static int
ahc_abort_scbs(struct ahc_softc *ahc, int target, char channel,
int lun, u_int tag, role_t role, uint32_t status)
{
@ -6078,7 +6650,7 @@ ahc_reset_channel(struct ahc_softc *ahc, char channel, int initiate_reset)
/*
* Calculate the residual for a just completed SCB.
*/
void
static void
ahc_calc_residual(struct ahc_softc *ahc, struct scb *scb)
{
struct hardware_scb *hscb;
@ -6279,7 +6851,7 @@ ahc_loadseq(struct ahc_softc *ahc)
struct cs cs_table[num_critical_sections];
u_int begin_set[num_critical_sections];
u_int end_set[num_critical_sections];
struct patch *cur_patch;
const struct patch *cur_patch;
u_int cs_count;
u_int cur_cs;
u_int i;
@ -6384,11 +6956,11 @@ ahc_loadseq(struct ahc_softc *ahc)
}
static int
ahc_check_patch(struct ahc_softc *ahc, struct patch **start_patch,
ahc_check_patch(struct ahc_softc *ahc, const struct patch **start_patch,
u_int start_instr, u_int *skip_addr)
{
struct patch *cur_patch;
struct patch *last_patch;
const struct patch *cur_patch;
const struct patch *last_patch;
u_int num_patches;
num_patches = ARRAY_SIZE(patches);
@ -6447,7 +7019,7 @@ ahc_download_instr(struct ahc_softc *ahc, u_int instrptr, uint8_t *dconsts)
case AIC_OP_JE:
case AIC_OP_JZ:
{
struct patch *cur_patch;
const struct patch *cur_patch;
int address_offset;
u_int address;
u_int skip_addr;
@ -6545,7 +7117,7 @@ ahc_download_instr(struct ahc_softc *ahc, u_int instrptr, uint8_t *dconsts)
}
int
ahc_print_register(ahc_reg_parse_entry_t *table, u_int num_entries,
ahc_print_register(const ahc_reg_parse_entry_t *table, u_int num_entries,
const char *name, u_int address, u_int value,
u_int *cur_column, u_int wrap_point)
{
@ -7229,7 +7801,7 @@ ahc_update_scsiid(struct ahc_softc *ahc, u_int targid_mask)
ahc_outb(ahc, SCSIID, scsiid);
}
void
static void
ahc_run_tqinfifo(struct ahc_softc *ahc, int paused)
{
struct target_cmd *cmd;

View File

@ -46,179 +46,13 @@
#define _AIC7XXX_INLINE_H_
/************************* Sequencer Execution Control ************************/
static __inline void ahc_pause_bug_fix(struct ahc_softc *ahc);
static __inline int ahc_is_paused(struct ahc_softc *ahc);
static __inline void ahc_pause(struct ahc_softc *ahc);
static __inline void ahc_unpause(struct ahc_softc *ahc);
/*
* Work around any chip bugs related to halting sequencer execution.
* On Ultra2 controllers, we must clear the CIOBUS stretch signal by
* reading a register that will set this signal and deassert it.
* Without this workaround, if the chip is paused, by an interrupt or
* manual pause while accessing scb ram, accesses to certain registers
* will hang the system (infinite pci retries).
*/
static __inline void
ahc_pause_bug_fix(struct ahc_softc *ahc)
{
if ((ahc->features & AHC_ULTRA2) != 0)
(void)ahc_inb(ahc, CCSCBCTL);
}
/*
* Determine whether the sequencer has halted code execution.
* Returns non-zero status if the sequencer is stopped.
*/
static __inline int
ahc_is_paused(struct ahc_softc *ahc)
{
return ((ahc_inb(ahc, HCNTRL) & PAUSE) != 0);
}
/*
* Request that the sequencer stop and wait, indefinitely, for it
* to stop. The sequencer will only acknowledge that it is paused
* once it has reached an instruction boundary and PAUSEDIS is
* cleared in the SEQCTL register. The sequencer may use PAUSEDIS
* for critical sections.
*/
static __inline void
ahc_pause(struct ahc_softc *ahc)
{
ahc_outb(ahc, HCNTRL, ahc->pause);
/*
* Since the sequencer can disable pausing in a critical section, we
* must loop until it actually stops.
*/
while (ahc_is_paused(ahc) == 0)
;
ahc_pause_bug_fix(ahc);
}
/*
* Allow the sequencer to continue program execution.
* We check here to ensure that no additional interrupt
* sources that would cause the sequencer to halt have been
* asserted. If, for example, a SCSI bus reset is detected
* while we are fielding a different, pausing, interrupt type,
* we don't want to release the sequencer before going back
* into our interrupt handler and dealing with this new
* condition.
*/
static __inline void
ahc_unpause(struct ahc_softc *ahc)
{
if ((ahc_inb(ahc, INTSTAT) & (SCSIINT | SEQINT | BRKADRINT)) == 0)
ahc_outb(ahc, HCNTRL, ahc->unpause);
}
/*********************** Untagged Transaction Routines ************************/
static __inline void ahc_freeze_untagged_queues(struct ahc_softc *ahc);
static __inline void ahc_release_untagged_queues(struct ahc_softc *ahc);
/*
* Block our completion routine from starting the next untagged
* transaction for this target or target lun.
*/
static __inline void
ahc_freeze_untagged_queues(struct ahc_softc *ahc)
{
if ((ahc->flags & AHC_SCB_BTT) == 0)
ahc->untagged_queue_lock++;
}
/*
* Allow the next untagged transaction for this target or target lun
* to be executed. We use a counting semaphore to allow the lock
* to be acquired recursively. Once the count drops to zero, the
* transaction queues will be run.
*/
static __inline void
ahc_release_untagged_queues(struct ahc_softc *ahc)
{
if ((ahc->flags & AHC_SCB_BTT) == 0) {
ahc->untagged_queue_lock--;
if (ahc->untagged_queue_lock == 0)
ahc_run_untagged_queues(ahc);
}
}
int ahc_is_paused(struct ahc_softc *ahc);
void ahc_pause(struct ahc_softc *ahc);
void ahc_unpause(struct ahc_softc *ahc);
/************************** Memory mapping routines ***************************/
static __inline struct ahc_dma_seg *
ahc_sg_bus_to_virt(struct scb *scb,
uint32_t sg_busaddr);
static __inline uint32_t
ahc_sg_virt_to_bus(struct scb *scb,
struct ahc_dma_seg *sg);
static __inline uint32_t
ahc_hscb_busaddr(struct ahc_softc *ahc, u_int index);
static __inline void ahc_sync_scb(struct ahc_softc *ahc,
struct scb *scb, int op);
static __inline void ahc_sync_sglist(struct ahc_softc *ahc,
struct scb *scb, int op);
static __inline uint32_t
ahc_targetcmd_offset(struct ahc_softc *ahc,
u_int index);
static __inline struct ahc_dma_seg *
ahc_sg_bus_to_virt(struct scb *scb, uint32_t sg_busaddr)
{
int sg_index;
sg_index = (sg_busaddr - scb->sg_list_phys)/sizeof(struct ahc_dma_seg);
/* sg_list_phys points to entry 1, not 0 */
sg_index++;
return (&scb->sg_list[sg_index]);
}
static __inline uint32_t
ahc_sg_virt_to_bus(struct scb *scb, struct ahc_dma_seg *sg)
{
int sg_index;
/* sg_list_phys points to entry 1, not 0 */
sg_index = sg - &scb->sg_list[1];
return (scb->sg_list_phys + (sg_index * sizeof(*scb->sg_list)));
}
static __inline uint32_t
ahc_hscb_busaddr(struct ahc_softc *ahc, u_int index)
{
return (ahc->scb_data->hscb_busaddr
+ (sizeof(struct hardware_scb) * index));
}
static __inline void
ahc_sync_scb(struct ahc_softc *ahc, struct scb *scb, int op)
{
ahc_dmamap_sync(ahc, ahc->scb_data->hscb_dmat,
ahc->scb_data->hscb_dmamap,
/*offset*/(scb->hscb - ahc->hscbs) * sizeof(*scb->hscb),
/*len*/sizeof(*scb->hscb), op);
}
static __inline void
ahc_sync_sglist(struct ahc_softc *ahc, struct scb *scb, int op)
{
if (scb->sg_count == 0)
return;
ahc_dmamap_sync(ahc, ahc->scb_data->sg_dmat, scb->sg_map->sg_dmamap,
/*offset*/(scb->sg_list - scb->sg_map->sg_vaddr)
* sizeof(struct ahc_dma_seg),
/*len*/sizeof(struct ahc_dma_seg) * scb->sg_count, op);
}
static __inline uint32_t
ahc_targetcmd_offset(struct ahc_softc *ahc, u_int index)
{
return (((uint8_t *)&ahc->targetcmds[index]) - ahc->qoutfifo);
}
void ahc_sync_sglist(struct ahc_softc *ahc,
struct scb *scb, int op);
/******************************** Debugging ***********************************/
static __inline char *ahc_name(struct ahc_softc *ahc);
@ -231,420 +65,34 @@ ahc_name(struct ahc_softc *ahc)
/*********************** Miscellaneous Support Functions ***********************/
static __inline void ahc_update_residual(struct ahc_softc *ahc,
struct scb *scb);
static __inline struct ahc_initiator_tinfo *
ahc_fetch_transinfo(struct ahc_softc *ahc,
char channel, u_int our_id,
u_int remote_id,
struct ahc_tmode_tstate **tstate);
static __inline uint16_t
ahc_inw(struct ahc_softc *ahc, u_int port);
static __inline void ahc_outw(struct ahc_softc *ahc, u_int port,
u_int value);
static __inline uint32_t
ahc_inl(struct ahc_softc *ahc, u_int port);
static __inline void ahc_outl(struct ahc_softc *ahc, u_int port,
uint32_t value);
static __inline uint64_t
ahc_inq(struct ahc_softc *ahc, u_int port);
static __inline void ahc_outq(struct ahc_softc *ahc, u_int port,
uint64_t value);
static __inline struct scb*
ahc_get_scb(struct ahc_softc *ahc);
static __inline void ahc_free_scb(struct ahc_softc *ahc, struct scb *scb);
static __inline void ahc_swap_with_next_hscb(struct ahc_softc *ahc,
struct scb *scb);
static __inline void ahc_queue_scb(struct ahc_softc *ahc, struct scb *scb);
static __inline struct scsi_sense_data *
ahc_get_sense_buf(struct ahc_softc *ahc,
struct scb *scb);
static __inline uint32_t
ahc_get_sense_bufaddr(struct ahc_softc *ahc,
struct scb *scb);
/*
* Determine whether the sequencer reported a residual
* for this SCB/transaction.
*/
static __inline void
ahc_update_residual(struct ahc_softc *ahc, struct scb *scb)
{
uint32_t sgptr;
sgptr = ahc_le32toh(scb->hscb->sgptr);
if ((sgptr & SG_RESID_VALID) != 0)
ahc_calc_residual(ahc, scb);
}
/*
* Return pointers to the transfer negotiation information
* for the specified our_id/remote_id pair.
*/
static __inline struct ahc_initiator_tinfo *
ahc_fetch_transinfo(struct ahc_softc *ahc, char channel, u_int our_id,
u_int remote_id, struct ahc_tmode_tstate **tstate)
{
/*
* Transfer data structures are stored from the perspective
* of the target role. Since the parameters for a connection
* in the initiator role to a given target are the same as
* when the roles are reversed, we pretend we are the target.
*/
if (channel == 'B')
our_id += 8;
*tstate = ahc->enabled_targets[our_id];
return (&(*tstate)->transinfo[remote_id]);
}
static __inline uint16_t
ahc_inw(struct ahc_softc *ahc, u_int port)
{
uint16_t r = ahc_inb(ahc, port+1) << 8;
return r | ahc_inb(ahc, port);
}
static __inline void
ahc_outw(struct ahc_softc *ahc, u_int port, u_int value)
{
ahc_outb(ahc, port, value & 0xFF);
ahc_outb(ahc, port+1, (value >> 8) & 0xFF);
}
static __inline uint32_t
ahc_inl(struct ahc_softc *ahc, u_int port)
{
return ((ahc_inb(ahc, port))
| (ahc_inb(ahc, port+1) << 8)
| (ahc_inb(ahc, port+2) << 16)
| (ahc_inb(ahc, port+3) << 24));
}
static __inline void
ahc_outl(struct ahc_softc *ahc, u_int port, uint32_t value)
{
ahc_outb(ahc, port, (value) & 0xFF);
ahc_outb(ahc, port+1, ((value) >> 8) & 0xFF);
ahc_outb(ahc, port+2, ((value) >> 16) & 0xFF);
ahc_outb(ahc, port+3, ((value) >> 24) & 0xFF);
}
static __inline uint64_t
ahc_inq(struct ahc_softc *ahc, u_int port)
{
return ((ahc_inb(ahc, port))
| (ahc_inb(ahc, port+1) << 8)
| (ahc_inb(ahc, port+2) << 16)
| (ahc_inb(ahc, port+3) << 24)
| (((uint64_t)ahc_inb(ahc, port+4)) << 32)
| (((uint64_t)ahc_inb(ahc, port+5)) << 40)
| (((uint64_t)ahc_inb(ahc, port+6)) << 48)
| (((uint64_t)ahc_inb(ahc, port+7)) << 56));
}
static __inline void
ahc_outq(struct ahc_softc *ahc, u_int port, uint64_t value)
{
ahc_outb(ahc, port, value & 0xFF);
ahc_outb(ahc, port+1, (value >> 8) & 0xFF);
ahc_outb(ahc, port+2, (value >> 16) & 0xFF);
ahc_outb(ahc, port+3, (value >> 24) & 0xFF);
ahc_outb(ahc, port+4, (value >> 32) & 0xFF);
ahc_outb(ahc, port+5, (value >> 40) & 0xFF);
ahc_outb(ahc, port+6, (value >> 48) & 0xFF);
ahc_outb(ahc, port+7, (value >> 56) & 0xFF);
}
/*
* Get a free scb. If there are none, see if we can allocate a new SCB.
*/
static __inline struct scb *
ahc_get_scb(struct ahc_softc *ahc)
{
struct scb *scb;
if ((scb = SLIST_FIRST(&ahc->scb_data->free_scbs)) == NULL) {
ahc_alloc_scbs(ahc);
scb = SLIST_FIRST(&ahc->scb_data->free_scbs);
if (scb == NULL)
return (NULL);
}
SLIST_REMOVE_HEAD(&ahc->scb_data->free_scbs, links.sle);
return (scb);
}
/*
* Return an SCB resource to the free list.
*/
static __inline void
ahc_free_scb(struct ahc_softc *ahc, struct scb *scb)
{
struct hardware_scb *hscb;
hscb = scb->hscb;
/* Clean up for the next user */
ahc->scb_data->scbindex[hscb->tag] = NULL;
scb->flags = SCB_FREE;
hscb->control = 0;
SLIST_INSERT_HEAD(&ahc->scb_data->free_scbs, scb, links.sle);
/* Notify the OSM that a resource is now available. */
ahc_platform_scb_free(ahc, scb);
}
static __inline struct scb *
ahc_lookup_scb(struct ahc_softc *ahc, u_int tag)
{
struct scb* scb;
scb = ahc->scb_data->scbindex[tag];
if (scb != NULL)
ahc_sync_scb(ahc, scb,
BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
return (scb);
}
static __inline void
ahc_swap_with_next_hscb(struct ahc_softc *ahc, struct scb *scb)
{
struct hardware_scb *q_hscb;
u_int saved_tag;
/*
* Our queuing method is a bit tricky. The card
* knows in advance which HSCB to download, and we
* can't disappoint it. To achieve this, the next
* SCB to download is saved off in ahc->next_queued_scb.
* When we are called to queue "an arbitrary scb",
* we copy the contents of the incoming HSCB to the one
* the sequencer knows about, swap HSCB pointers and
* finally assign the SCB to the tag indexed location
* in the scb_array. This makes sure that we can still
* locate the correct SCB by SCB_TAG.
*/
q_hscb = ahc->next_queued_scb->hscb;
saved_tag = q_hscb->tag;
memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb));
if ((scb->flags & SCB_CDB32_PTR) != 0) {
q_hscb->shared_data.cdb_ptr =
ahc_htole32(ahc_hscb_busaddr(ahc, q_hscb->tag)
+ offsetof(struct hardware_scb, cdb32));
}
q_hscb->tag = saved_tag;
q_hscb->next = scb->hscb->tag;
/* Now swap HSCB pointers. */
ahc->next_queued_scb->hscb = scb->hscb;
scb->hscb = q_hscb;
/* Now define the mapping from tag to SCB in the scbindex */
ahc->scb_data->scbindex[scb->hscb->tag] = scb;
}
/*
* Tell the sequencer about a new transaction to execute.
*/
static __inline void
ahc_queue_scb(struct ahc_softc *ahc, struct scb *scb)
{
ahc_swap_with_next_hscb(ahc, scb);
if (scb->hscb->tag == SCB_LIST_NULL
|| scb->hscb->next == SCB_LIST_NULL)
panic("Attempt to queue invalid SCB tag %x:%x\n",
scb->hscb->tag, scb->hscb->next);
/*
* Setup data "oddness".
*/
scb->hscb->lun &= LID;
if (ahc_get_transfer_length(scb) & 0x1)
scb->hscb->lun |= SCB_XFERLEN_ODD;
/*
* Keep a history of SCBs we've downloaded in the qinfifo.
*/
ahc->qinfifo[ahc->qinfifonext++] = scb->hscb->tag;
/*
* Make sure our data is consistent from the
* perspective of the adapter.
*/
ahc_sync_scb(ahc, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
/* Tell the adapter about the newly queued SCB */
if ((ahc->features & AHC_QUEUE_REGS) != 0) {
ahc_outb(ahc, HNSCB_QOFF, ahc->qinfifonext);
} else {
if ((ahc->features & AHC_AUTOPAUSE) == 0)
ahc_pause(ahc);
ahc_outb(ahc, KERNEL_QINPOS, ahc->qinfifonext);
if ((ahc->features & AHC_AUTOPAUSE) == 0)
ahc_unpause(ahc);
}
}
static __inline struct scsi_sense_data *
ahc_get_sense_buf(struct ahc_softc *ahc, struct scb *scb)
{
int offset;
offset = scb - ahc->scb_data->scbarray;
return (&ahc->scb_data->sense[offset]);
}
static __inline uint32_t
ahc_get_sense_bufaddr(struct ahc_softc *ahc, struct scb *scb)
{
int offset;
offset = scb - ahc->scb_data->scbarray;
return (ahc->scb_data->sense_busaddr
+ (offset * sizeof(struct scsi_sense_data)));
}
struct ahc_initiator_tinfo *
ahc_fetch_transinfo(struct ahc_softc *ahc,
char channel, u_int our_id,
u_int remote_id,
struct ahc_tmode_tstate **tstate);
uint16_t
ahc_inw(struct ahc_softc *ahc, u_int port);
void ahc_outw(struct ahc_softc *ahc, u_int port,
u_int value);
uint32_t
ahc_inl(struct ahc_softc *ahc, u_int port);
void ahc_outl(struct ahc_softc *ahc, u_int port,
uint32_t value);
uint64_t
ahc_inq(struct ahc_softc *ahc, u_int port);
void ahc_outq(struct ahc_softc *ahc, u_int port,
uint64_t value);
struct scb*
ahc_get_scb(struct ahc_softc *ahc);
void ahc_free_scb(struct ahc_softc *ahc, struct scb *scb);
struct scb *
ahc_lookup_scb(struct ahc_softc *ahc, u_int tag);
void ahc_queue_scb(struct ahc_softc *ahc, struct scb *scb);
struct scsi_sense_data *
ahc_get_sense_buf(struct ahc_softc *ahc,
struct scb *scb);
/************************** Interrupt Processing ******************************/
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 int ahc_intr(struct ahc_softc *ahc);
static __inline void
ahc_sync_qoutfifo(struct ahc_softc *ahc, int op)
{
ahc_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap,
/*offset*/0, /*len*/256, op);
}
static __inline void
ahc_sync_tqinfifo(struct ahc_softc *ahc, int op)
{
#ifdef AHC_TARGET_MODE
if ((ahc->flags & AHC_TARGETROLE) != 0) {
ahc_dmamap_sync(ahc, ahc->shared_data_dmat,
ahc->shared_data_dmamap,
ahc_targetcmd_offset(ahc, 0),
sizeof(struct target_cmd) * AHC_TMODE_CMDS,
op);
}
#endif
}
/*
* See if the firmware has posted any completed commands
* into our in-core command complete fifos.
*/
#define AHC_RUN_QOUTFIFO 0x1
#define AHC_RUN_TQINFIFO 0x2
static __inline u_int
ahc_check_cmdcmpltqueues(struct ahc_softc *ahc)
{
u_int retval;
retval = 0;
ahc_dmamap_sync(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap,
/*offset*/ahc->qoutfifonext, /*len*/1,
BUS_DMASYNC_POSTREAD);
if (ahc->qoutfifo[ahc->qoutfifonext] != SCB_LIST_NULL)
retval |= AHC_RUN_QOUTFIFO;
#ifdef AHC_TARGET_MODE
if ((ahc->flags & AHC_TARGETROLE) != 0
&& (ahc->flags & AHC_TQINFIFO_BLOCKED) == 0) {
ahc_dmamap_sync(ahc, ahc->shared_data_dmat,
ahc->shared_data_dmamap,
ahc_targetcmd_offset(ahc, ahc->tqinfifofnext),
/*len*/sizeof(struct target_cmd),
BUS_DMASYNC_POSTREAD);
if (ahc->targetcmds[ahc->tqinfifonext].cmd_valid != 0)
retval |= AHC_RUN_TQINFIFO;
}
#endif
return (retval);
}
/*
* Catch an interrupt from the adapter
*/
static __inline int
ahc_intr(struct ahc_softc *ahc)
{
u_int intstat;
if ((ahc->pause & INTEN) == 0) {
/*
* Our interrupt is not enabled on the chip
* and may be disabled for re-entrancy reasons,
* so just return. This is likely just a shared
* interrupt.
*/
return (0);
}
/*
* Instead of directly reading the interrupt status register,
* infer the cause of the interrupt by checking our in-core
* completion queues. This avoids a costly PCI bus read in
* most cases.
*/
if ((ahc->flags & (AHC_ALL_INTERRUPTS|AHC_EDGE_INTERRUPT)) == 0
&& (ahc_check_cmdcmpltqueues(ahc) != 0))
intstat = CMDCMPLT;
else {
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);
/*
* Ensure that the chip sees that we've cleared
* this interrupt before we walk the output fifo.
* Otherwise, we may, due to posted bus writes,
* clear the interrupt after we finish the scan,
* and after the sequencer has added new entries
* and asserted the interrupt again.
*/
ahc_flush_device_writes(ahc);
ahc_run_qoutfifo(ahc);
#ifdef AHC_TARGET_MODE
if ((ahc->flags & AHC_TARGETROLE) != 0)
ahc_run_tqinfifo(ahc, /*paused*/FALSE);
#endif
}
/*
* 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);
} else if ((intstat & (SEQINT|SCSIINT)) != 0) {
ahc_pause_bug_fix(ahc);
if ((intstat & SEQINT) != 0)
ahc_handle_seqint(ahc, intstat);
if ((intstat & SCSIINT) != 0)
ahc_handle_scsiint(ahc, intstat);
}
return (1);
}
int ahc_intr(struct ahc_softc *ahc);
#endif /* _AIC7XXX_INLINE_H_ */

View File

@ -388,14 +388,83 @@ static int aic7xxx_setup(char *s);
static int ahc_linux_unit;
/********************************* Inlines ************************************/
static __inline void ahc_linux_unmap_scb(struct ahc_softc*, struct scb*);
/************************** OS Utility Wrappers *******************************/
void
ahc_delay(long usec)
{
/*
* udelay on Linux can have problems for
* multi-millisecond waits. Wait at most
* 1024us per call.
*/
while (usec > 0) {
udelay(usec % 1024);
usec -= 1024;
}
}
static __inline int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb,
/***************************** Low Level I/O **********************************/
uint8_t
ahc_inb(struct ahc_softc * ahc, long port)
{
uint8_t x;
if (ahc->tag == BUS_SPACE_MEMIO) {
x = readb(ahc->bsh.maddr + port);
} else {
x = inb(ahc->bsh.ioport + port);
}
mb();
return (x);
}
void
ahc_outb(struct ahc_softc * ahc, long port, uint8_t val)
{
if (ahc->tag == BUS_SPACE_MEMIO) {
writeb(val, ahc->bsh.maddr + port);
} else {
outb(val, ahc->bsh.ioport + port);
}
mb();
}
void
ahc_outsb(struct ahc_softc * ahc, long port, uint8_t *array, int count)
{
int i;
/*
* There is probably a more efficient way to do this on Linux
* but we don't use this for anything speed critical and this
* should work.
*/
for (i = 0; i < count; i++)
ahc_outb(ahc, port, *array++);
}
void
ahc_insb(struct ahc_softc * ahc, long port, uint8_t *array, int count)
{
int i;
/*
* There is probably a more efficient way to do this on Linux
* but we don't use this for anything speed critical and this
* should work.
*/
for (i = 0; i < count; i++)
*array++ = ahc_inb(ahc, port);
}
/********************************* Inlines ************************************/
static void ahc_linux_unmap_scb(struct ahc_softc*, struct scb*);
static int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb,
struct ahc_dma_seg *sg,
dma_addr_t addr, bus_size_t len);
static __inline void
static void
ahc_linux_unmap_scb(struct ahc_softc *ahc, struct scb *scb)
{
struct scsi_cmnd *cmd;
@ -406,7 +475,7 @@ ahc_linux_unmap_scb(struct ahc_softc *ahc, struct scb *scb)
scsi_dma_unmap(cmd);
}
static __inline int
static int
ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb,
struct ahc_dma_seg *sg, dma_addr_t addr, bus_size_t len)
{
@ -442,13 +511,11 @@ ahc_linux_info(struct Scsi_Host *host)
bp = &buffer[0];
ahc = *(struct ahc_softc **)host->hostdata;
memset(bp, 0, sizeof(buffer));
strcpy(bp, "Adaptec AIC7XXX EISA/VLB/PCI SCSI HBA DRIVER, Rev ");
strcat(bp, AIC7XXX_DRIVER_VERSION);
strcat(bp, "\n");
strcat(bp, " <");
strcpy(bp, "Adaptec AIC7XXX EISA/VLB/PCI SCSI HBA DRIVER, Rev " AIC7XXX_DRIVER_VERSION "\n"
" <");
strcat(bp, ahc->description);
strcat(bp, ">\n");
strcat(bp, " ");
strcat(bp, ">\n"
" ");
ahc_controller_info(ahc, ahc_info);
strcat(bp, ahc_info);
strcat(bp, "\n");
@ -964,7 +1031,7 @@ aic7xxx_setup(char *s)
char *p;
char *end;
static struct {
static const struct {
const char *name;
uint32_t *flag;
} options[] = {
@ -2317,7 +2384,7 @@ static void ahc_linux_set_period(struct scsi_target *starget, int period)
unsigned int ppr_options = tinfo->goal.ppr_options;
unsigned long flags;
unsigned long offset = tinfo->goal.offset;
struct ahc_syncrate *syncrate;
const struct ahc_syncrate *syncrate;
if (offset == 0)
offset = MAX_OFFSET;
@ -2361,7 +2428,7 @@ static void ahc_linux_set_offset(struct scsi_target *starget, int offset)
unsigned int ppr_options = 0;
unsigned int period = 0;
unsigned long flags;
struct ahc_syncrate *syncrate = NULL;
const struct ahc_syncrate *syncrate = NULL;
ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
starget->channel + 'A', ROLE_INITIATOR);
@ -2391,7 +2458,7 @@ static void ahc_linux_set_dt(struct scsi_target *starget, int dt)
unsigned int period = tinfo->goal.period;
unsigned int width = tinfo->goal.width;
unsigned long flags;
struct ahc_syncrate *syncrate;
const struct ahc_syncrate *syncrate;
if (dt && spi_max_width(starget)) {
ppr_options |= MSG_EXT_PPR_DT_REQ;

View File

@ -365,7 +365,7 @@ struct ahc_platform_data {
#define AHC_LINUX_NOIRQ ((uint32_t)~0)
uint32_t irq; /* IRQ for this adapter */
uint32_t bios_address;
uint32_t mem_busaddr; /* Mem Base Addr */
resource_size_t mem_busaddr; /* Mem Base Addr */
};
/************************** OS Utility Wrappers *******************************/
@ -375,82 +375,16 @@ struct ahc_platform_data {
#define malloc(size, type, flags) kmalloc(size, flags)
#define free(ptr, type) kfree(ptr)
static __inline void ahc_delay(long);
static __inline void
ahc_delay(long usec)
{
/*
* udelay on Linux can have problems for
* multi-millisecond waits. Wait at most
* 1024us per call.
*/
while (usec > 0) {
udelay(usec % 1024);
usec -= 1024;
}
}
void ahc_delay(long);
/***************************** Low Level I/O **********************************/
static __inline uint8_t ahc_inb(struct ahc_softc * ahc, long port);
static __inline void ahc_outb(struct ahc_softc * ahc, long port, uint8_t val);
static __inline void ahc_outsb(struct ahc_softc * ahc, long port,
uint8_t *, int count);
static __inline void ahc_insb(struct ahc_softc * ahc, long port,
uint8_t *, int count);
static __inline uint8_t
ahc_inb(struct ahc_softc * ahc, long port)
{
uint8_t x;
if (ahc->tag == BUS_SPACE_MEMIO) {
x = readb(ahc->bsh.maddr + port);
} else {
x = inb(ahc->bsh.ioport + port);
}
mb();
return (x);
}
static __inline void
ahc_outb(struct ahc_softc * ahc, long port, uint8_t val)
{
if (ahc->tag == BUS_SPACE_MEMIO) {
writeb(val, ahc->bsh.maddr + port);
} else {
outb(val, ahc->bsh.ioport + port);
}
mb();
}
static __inline void
ahc_outsb(struct ahc_softc * ahc, long port, uint8_t *array, int count)
{
int i;
/*
* There is probably a more efficient way to do this on Linux
* but we don't use this for anything speed critical and this
* should work.
*/
for (i = 0; i < count; i++)
ahc_outb(ahc, port, *array++);
}
static __inline void
ahc_insb(struct ahc_softc * ahc, long port, uint8_t *array, int count)
{
int i;
/*
* There is probably a more efficient way to do this on Linux
* but we don't use this for anything speed critical and this
* should work.
*/
for (i = 0; i < count; i++)
*array++ = ahc_inb(ahc, port);
}
uint8_t ahc_inb(struct ahc_softc * ahc, long port);
void ahc_outb(struct ahc_softc * ahc, long port, uint8_t val);
void ahc_outsb(struct ahc_softc * ahc, long port,
uint8_t *, int count);
void ahc_insb(struct ahc_softc * ahc, long port,
uint8_t *, int count);
/**************************** Initialization **********************************/
int ahc_linux_register_host(struct ahc_softc *,
@ -464,9 +398,6 @@ struct info_str {
int pos;
};
void ahc_format_transinfo(struct info_str *info,
struct ahc_transinfo *tinfo);
/******************************** Locking *************************************/
/* Lock protecting internal data structures */
@ -555,61 +486,12 @@ void ahc_linux_pci_exit(void);
int ahc_pci_map_registers(struct ahc_softc *ahc);
int ahc_pci_map_int(struct ahc_softc *ahc);
static __inline uint32_t ahc_pci_read_config(ahc_dev_softc_t pci,
uint32_t ahc_pci_read_config(ahc_dev_softc_t pci,
int reg, int width);
static __inline uint32_t
ahc_pci_read_config(ahc_dev_softc_t pci, int reg, int width)
{
switch (width) {
case 1:
{
uint8_t retval;
pci_read_config_byte(pci, reg, &retval);
return (retval);
}
case 2:
{
uint16_t retval;
pci_read_config_word(pci, reg, &retval);
return (retval);
}
case 4:
{
uint32_t retval;
pci_read_config_dword(pci, reg, &retval);
return (retval);
}
default:
panic("ahc_pci_read_config: Read size too big");
/* NOTREACHED */
return (0);
}
}
static __inline void ahc_pci_write_config(ahc_dev_softc_t pci,
int reg, uint32_t value,
int width);
static __inline void
ahc_pci_write_config(ahc_dev_softc_t pci, int reg, uint32_t value, int width)
{
switch (width) {
case 1:
pci_write_config_byte(pci, reg, value);
break;
case 2:
pci_write_config_word(pci, reg, value);
break;
case 4:
pci_write_config_dword(pci, reg, value);
break;
default:
panic("ahc_pci_write_config: Write size too big");
/* NOTREACHED */
}
}
void ahc_pci_write_config(ahc_dev_softc_t pci,
int reg, uint32_t value,
int width);
static __inline int ahc_get_pci_function(ahc_dev_softc_t);
static __inline int

View File

@ -46,7 +46,7 @@
*/
#define ID(x) ID_C(x, PCI_CLASS_STORAGE_SCSI)
static struct pci_device_id ahc_linux_pci_id_table[] = {
static const struct pci_device_id ahc_linux_pci_id_table[] = {
/* aic7850 based controllers */
ID(ID_AHA_2902_04_10_15_20C_30C),
/* aic7860 based controllers */
@ -206,7 +206,7 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
const uint64_t mask_39bit = 0x7FFFFFFFFFULL;
struct ahc_softc *ahc;
ahc_dev_softc_t pci;
struct ahc_pci_identity *entry;
const struct ahc_pci_identity *entry;
char *name;
int error;
struct device *dev = &pdev->dev;
@ -269,6 +269,57 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
return (0);
}
/******************************* PCI Routines *********************************/
uint32_t
ahc_pci_read_config(ahc_dev_softc_t pci, int reg, int width)
{
switch (width) {
case 1:
{
uint8_t retval;
pci_read_config_byte(pci, reg, &retval);
return (retval);
}
case 2:
{
uint16_t retval;
pci_read_config_word(pci, reg, &retval);
return (retval);
}
case 4:
{
uint32_t retval;
pci_read_config_dword(pci, reg, &retval);
return (retval);
}
default:
panic("ahc_pci_read_config: Read size too big");
/* NOTREACHED */
return (0);
}
}
void
ahc_pci_write_config(ahc_dev_softc_t pci, int reg, uint32_t value, int width)
{
switch (width) {
case 1:
pci_write_config_byte(pci, reg, value);
break;
case 2:
pci_write_config_word(pci, reg, value);
break;
case 4:
pci_write_config_dword(pci, reg, value);
break;
default:
panic("ahc_pci_write_config: Write size too big");
/* NOTREACHED */
}
}
static struct pci_driver aic7xxx_pci_driver = {
.name = "aic7xxx",
.probe = ahc_linux_pci_dev_probe,
@ -293,7 +344,7 @@ ahc_linux_pci_exit(void)
}
static int
ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc, u_long *base)
ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc, resource_size_t *base)
{
if (aic7xxx_allow_memio == 0)
return (ENOMEM);
@ -308,10 +359,10 @@ ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc, u_long *base)
static int
ahc_linux_pci_reserve_mem_region(struct ahc_softc *ahc,
u_long *bus_addr,
resource_size_t *bus_addr,
uint8_t __iomem **maddr)
{
u_long start;
resource_size_t start;
int error;
error = 0;
@ -336,7 +387,7 @@ int
ahc_pci_map_registers(struct ahc_softc *ahc)
{
uint32_t command;
u_long base;
resource_size_t base;
uint8_t __iomem *maddr;
int error;
@ -374,12 +425,12 @@ ahc_pci_map_registers(struct ahc_softc *ahc)
} else
command |= PCIM_CMD_MEMEN;
} else {
printf("aic7xxx: PCI%d:%d:%d MEM region 0x%lx "
printf("aic7xxx: PCI%d:%d:%d MEM region 0x%llx "
"unavailable. Cannot memory map device.\n",
ahc_get_pci_bus(ahc->dev_softc),
ahc_get_pci_slot(ahc->dev_softc),
ahc_get_pci_function(ahc->dev_softc),
base);
(unsigned long long)base);
}
/*
@ -390,15 +441,15 @@ ahc_pci_map_registers(struct ahc_softc *ahc)
error = ahc_linux_pci_reserve_io_region(ahc, &base);
if (error == 0) {
ahc->tag = BUS_SPACE_PIO;
ahc->bsh.ioport = base;
ahc->bsh.ioport = (u_long)base;
command |= PCIM_CMD_PORTEN;
} else {
printf("aic7xxx: PCI%d:%d:%d IO region 0x%lx[0..255] "
printf("aic7xxx: PCI%d:%d:%d IO region 0x%llx[0..255] "
"unavailable. Cannot map device.\n",
ahc_get_pci_bus(ahc->dev_softc),
ahc_get_pci_slot(ahc->dev_softc),
ahc_get_pci_function(ahc->dev_softc),
base);
(unsigned long long)base);
}
}
ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, 4);

View File

@ -168,8 +168,7 @@ static ahc_device_setup_t ahc_aha394XX_setup;
static ahc_device_setup_t ahc_aha494XX_setup;
static ahc_device_setup_t ahc_aha398XX_setup;
static struct ahc_pci_identity ahc_pci_ident_table [] =
{
static const struct ahc_pci_identity ahc_pci_ident_table[] = {
/* aic7850 based controllers */
{
ID_AHA_2902_04_10_15_20C_30C,
@ -668,7 +667,7 @@ ahc_9005_subdevinfo_valid(uint16_t device, uint16_t vendor,
return (result);
}
struct ahc_pci_identity *
const struct ahc_pci_identity *
ahc_find_pci_device(ahc_dev_softc_t pci)
{
uint64_t full_id;
@ -676,7 +675,7 @@ ahc_find_pci_device(ahc_dev_softc_t pci)
uint16_t vendor;
uint16_t subdevice;
uint16_t subvendor;
struct ahc_pci_identity *entry;
const struct ahc_pci_identity *entry;
u_int i;
vendor = ahc_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2);
@ -710,7 +709,7 @@ ahc_find_pci_device(ahc_dev_softc_t pci)
}
int
ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
ahc_pci_config(struct ahc_softc *ahc, const struct ahc_pci_identity *entry)
{
u_int command;
u_int our_id;

View File

@ -58,7 +58,7 @@ static int ahc_proc_write_seeprom(struct ahc_softc *ahc,
* Table of syncrates that don't follow the "divisible by 4"
* rule. This table will be expanded in future SCSI specs.
*/
static struct {
static const struct {
u_int period_factor;
u_int period; /* in 100ths of ns */
} scsi_syncrates[] = {
@ -137,7 +137,7 @@ copy_info(struct info_str *info, char *fmt, ...)
return (len);
}
void
static void
ahc_format_transinfo(struct info_str *info, struct ahc_transinfo *tinfo)
{
u_int speed;

View File

@ -8,7 +8,7 @@
#include "aic7xxx_osm.h"
static ahc_reg_parse_entry_t SCSISEQ_parse_table[] = {
static const ahc_reg_parse_entry_t SCSISEQ_parse_table[] = {
{ "SCSIRSTO", 0x01, 0x01 },
{ "ENAUTOATNP", 0x02, 0x02 },
{ "ENAUTOATNI", 0x04, 0x04 },
@ -26,7 +26,7 @@ ahc_scsiseq_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x00, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SXFRCTL0_parse_table[] = {
static const ahc_reg_parse_entry_t SXFRCTL0_parse_table[] = {
{ "CLRCHN", 0x02, 0x02 },
{ "SCAMEN", 0x04, 0x04 },
{ "SPIOEN", 0x08, 0x08 },
@ -43,7 +43,7 @@ ahc_sxfrctl0_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x01, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SXFRCTL1_parse_table[] = {
static const ahc_reg_parse_entry_t SXFRCTL1_parse_table[] = {
{ "STPWEN", 0x01, 0x01 },
{ "ACTNEGEN", 0x02, 0x02 },
{ "ENSTIMER", 0x04, 0x04 },
@ -60,7 +60,7 @@ ahc_sxfrctl1_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x02, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SCSISIGO_parse_table[] = {
static const ahc_reg_parse_entry_t SCSISIGO_parse_table[] = {
{ "ACKO", 0x01, 0x01 },
{ "REQO", 0x02, 0x02 },
{ "BSYO", 0x04, 0x04 },
@ -85,7 +85,7 @@ ahc_scsisigo_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x03, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SCSISIGI_parse_table[] = {
static const ahc_reg_parse_entry_t SCSISIGI_parse_table[] = {
{ "ACKI", 0x01, 0x01 },
{ "REQI", 0x02, 0x02 },
{ "BSYI", 0x04, 0x04 },
@ -112,7 +112,7 @@ ahc_scsisigi_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x03, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SCSIRATE_parse_table[] = {
static const ahc_reg_parse_entry_t SCSIRATE_parse_table[] = {
{ "SINGLE_EDGE", 0x10, 0x10 },
{ "ENABLE_CRC", 0x40, 0x40 },
{ "WIDEXFER", 0x80, 0x80 },
@ -128,7 +128,7 @@ ahc_scsirate_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x04, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SCSIID_parse_table[] = {
static const ahc_reg_parse_entry_t SCSIID_parse_table[] = {
{ "TWIN_CHNLB", 0x80, 0x80 },
{ "OID", 0x0f, 0x0f },
{ "TWIN_TID", 0x70, 0x70 },
@ -150,13 +150,6 @@ ahc_scsidatl_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x06, regvalue, cur_col, wrap));
}
int
ahc_scsidath_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahc_print_register(NULL, 0, "SCSIDATH",
0x07, regvalue, cur_col, wrap));
}
int
ahc_stcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
@ -164,7 +157,7 @@ ahc_stcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x08, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t OPTIONMODE_parse_table[] = {
static const ahc_reg_parse_entry_t OPTIONMODE_parse_table[] = {
{ "DIS_MSGIN_DUALEDGE", 0x01, 0x01 },
{ "AUTO_MSGOUT_DE", 0x02, 0x02 },
{ "SCSIDATL_IMGEN", 0x04, 0x04 },
@ -190,7 +183,7 @@ ahc_targcrccnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x0a, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t CLRSINT0_parse_table[] = {
static const ahc_reg_parse_entry_t CLRSINT0_parse_table[] = {
{ "CLRSPIORDY", 0x02, 0x02 },
{ "CLRSWRAP", 0x08, 0x08 },
{ "CLRIOERR", 0x08, 0x08 },
@ -206,7 +199,7 @@ ahc_clrsint0_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x0b, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SSTAT0_parse_table[] = {
static const ahc_reg_parse_entry_t SSTAT0_parse_table[] = {
{ "DMADONE", 0x01, 0x01 },
{ "SPIORDY", 0x02, 0x02 },
{ "SDONE", 0x04, 0x04 },
@ -225,7 +218,7 @@ ahc_sstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x0b, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t CLRSINT1_parse_table[] = {
static const ahc_reg_parse_entry_t CLRSINT1_parse_table[] = {
{ "CLRREQINIT", 0x01, 0x01 },
{ "CLRPHASECHG", 0x02, 0x02 },
{ "CLRSCSIPERR", 0x04, 0x04 },
@ -242,7 +235,7 @@ ahc_clrsint1_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x0c, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SSTAT1_parse_table[] = {
static const ahc_reg_parse_entry_t SSTAT1_parse_table[] = {
{ "REQINIT", 0x01, 0x01 },
{ "PHASECHG", 0x02, 0x02 },
{ "SCSIPERR", 0x04, 0x04 },
@ -260,7 +253,7 @@ ahc_sstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x0c, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SSTAT2_parse_table[] = {
static const ahc_reg_parse_entry_t SSTAT2_parse_table[] = {
{ "DUAL_EDGE_ERR", 0x01, 0x01 },
{ "CRCREQERR", 0x02, 0x02 },
{ "CRCENDERR", 0x04, 0x04 },
@ -278,7 +271,7 @@ ahc_sstat2_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x0d, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SSTAT3_parse_table[] = {
static const ahc_reg_parse_entry_t SSTAT3_parse_table[] = {
{ "OFFCNT", 0x0f, 0x0f },
{ "U2OFFCNT", 0x7f, 0x7f },
{ "SCSICNT", 0xf0, 0xf0 }
@ -291,7 +284,7 @@ ahc_sstat3_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x0e, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SCSIID_ULTRA2_parse_table[] = {
static const ahc_reg_parse_entry_t SCSIID_ULTRA2_parse_table[] = {
{ "OID", 0x0f, 0x0f },
{ "TID", 0xf0, 0xf0 }
};
@ -303,7 +296,7 @@ ahc_scsiid_ultra2_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x0f, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SIMODE0_parse_table[] = {
static const ahc_reg_parse_entry_t SIMODE0_parse_table[] = {
{ "ENDMADONE", 0x01, 0x01 },
{ "ENSPIORDY", 0x02, 0x02 },
{ "ENSDONE", 0x04, 0x04 },
@ -321,7 +314,7 @@ ahc_simode0_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x10, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SIMODE1_parse_table[] = {
static const ahc_reg_parse_entry_t SIMODE1_parse_table[] = {
{ "ENREQINIT", 0x01, 0x01 },
{ "ENPHASECHG", 0x02, 0x02 },
{ "ENSCSIPERR", 0x04, 0x04 },
@ -346,26 +339,6 @@ ahc_scsibusl_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x12, regvalue, cur_col, wrap));
}
int
ahc_scsibush_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahc_print_register(NULL, 0, "SCSIBUSH",
0x13, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SXFRCTL2_parse_table[] = {
{ "CMDDMAEN", 0x08, 0x08 },
{ "AUTORSTDIS", 0x10, 0x10 },
{ "ASYNC_SETUP", 0x07, 0x07 }
};
int
ahc_sxfrctl2_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahc_print_register(SXFRCTL2_parse_table, 3, "SXFRCTL2",
0x13, regvalue, cur_col, wrap));
}
int
ahc_shaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
@ -373,7 +346,7 @@ ahc_shaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x14, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SELTIMER_parse_table[] = {
static const ahc_reg_parse_entry_t SELTIMER_parse_table[] = {
{ "STAGE1", 0x01, 0x01 },
{ "STAGE2", 0x02, 0x02 },
{ "STAGE3", 0x04, 0x04 },
@ -389,7 +362,7 @@ ahc_seltimer_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x18, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SELID_parse_table[] = {
static const ahc_reg_parse_entry_t SELID_parse_table[] = {
{ "ONEBIT", 0x08, 0x08 },
{ "SELID_MASK", 0xf0, 0xf0 }
};
@ -401,21 +374,6 @@ ahc_selid_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x19, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SCAMCTL_parse_table[] = {
{ "DFLTTID", 0x10, 0x10 },
{ "ALTSTIM", 0x20, 0x20 },
{ "CLRSCAMSELID", 0x40, 0x40 },
{ "ENSCAMSELO", 0x80, 0x80 },
{ "SCAMLVL", 0x03, 0x03 }
};
int
ahc_scamctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahc_print_register(SCAMCTL_parse_table, 5, "SCAMCTL",
0x1a, regvalue, cur_col, wrap));
}
int
ahc_targid_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
@ -423,7 +381,7 @@ ahc_targid_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x1b, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SPIOCAP_parse_table[] = {
static const ahc_reg_parse_entry_t SPIOCAP_parse_table[] = {
{ "SSPIOCPS", 0x01, 0x01 },
{ "ROM", 0x02, 0x02 },
{ "EEPROM", 0x04, 0x04 },
@ -441,7 +399,7 @@ ahc_spiocap_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x1b, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t BRDCTL_parse_table[] = {
static const ahc_reg_parse_entry_t BRDCTL_parse_table[] = {
{ "BRDCTL0", 0x01, 0x01 },
{ "BRDSTB_ULTRA2", 0x01, 0x01 },
{ "BRDCTL1", 0x02, 0x02 },
@ -464,7 +422,7 @@ ahc_brdctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x1d, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SEECTL_parse_table[] = {
static const ahc_reg_parse_entry_t SEECTL_parse_table[] = {
{ "SEEDI", 0x01, 0x01 },
{ "SEEDO", 0x02, 0x02 },
{ "SEECK", 0x04, 0x04 },
@ -482,7 +440,7 @@ ahc_seectl_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x1e, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SBLKCTL_parse_table[] = {
static const ahc_reg_parse_entry_t SBLKCTL_parse_table[] = {
{ "XCVR", 0x01, 0x01 },
{ "SELWIDE", 0x02, 0x02 },
{ "ENAB20", 0x04, 0x04 },
@ -521,13 +479,6 @@ ahc_disc_dsb_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x32, regvalue, cur_col, wrap));
}
int
ahc_cmdsize_table_tail_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahc_print_register(NULL, 0, "CMDSIZE_TABLE_TAIL",
0x34, regvalue, cur_col, wrap));
}
int
ahc_mwi_residual_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
@ -549,7 +500,7 @@ ahc_msg_out_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x3a, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t DMAPARAMS_parse_table[] = {
static const ahc_reg_parse_entry_t DMAPARAMS_parse_table[] = {
{ "FIFORESET", 0x01, 0x01 },
{ "FIFOFLUSH", 0x02, 0x02 },
{ "DIRECTION", 0x04, 0x04 },
@ -569,7 +520,7 @@ ahc_dmaparams_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x3b, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SEQ_FLAGS_parse_table[] = {
static const ahc_reg_parse_entry_t SEQ_FLAGS_parse_table[] = {
{ "NO_DISCONNECT", 0x01, 0x01 },
{ "SPHASE_PENDING", 0x02, 0x02 },
{ "DPHASE_PENDING", 0x04, 0x04 },
@ -602,7 +553,7 @@ ahc_saved_lun_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x3e, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t LASTPHASE_parse_table[] = {
static const ahc_reg_parse_entry_t LASTPHASE_parse_table[] = {
{ "MSGI", 0x20, 0x20 },
{ "IOI", 0x40, 0x40 },
{ "CDI", 0x80, 0x80 },
@ -644,13 +595,6 @@ ahc_free_scbh_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x42, regvalue, cur_col, wrap));
}
int
ahc_complete_scbh_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahc_print_register(NULL, 0, "COMPLETE_SCBH",
0x43, regvalue, cur_col, wrap));
}
int
ahc_hscb_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
@ -700,7 +644,7 @@ ahc_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x50, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t ARG_1_parse_table[] = {
static const ahc_reg_parse_entry_t ARG_1_parse_table[] = {
{ "CONT_TARG_SESSION", 0x02, 0x02 },
{ "CONT_MSG_LOOP", 0x04, 0x04 },
{ "EXIT_MSG_LOOP", 0x08, 0x08 },
@ -731,7 +675,7 @@ ahc_last_msg_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x53, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SCSISEQ_TEMPLATE_parse_table[] = {
static const ahc_reg_parse_entry_t SCSISEQ_TEMPLATE_parse_table[] = {
{ "ENAUTOATNP", 0x02, 0x02 },
{ "ENAUTOATNI", 0x04, 0x04 },
{ "ENAUTOATNO", 0x08, 0x08 },
@ -747,7 +691,7 @@ ahc_scsiseq_template_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x54, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t HA_274_BIOSGLOBAL_parse_table[] = {
static const ahc_reg_parse_entry_t HA_274_BIOSGLOBAL_parse_table[] = {
{ "HA_274_EXTENDED_TRANS",0x01, 0x01 }
};
@ -758,7 +702,7 @@ ahc_ha_274_biosglobal_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x56, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SEQ_FLAGS2_parse_table[] = {
static const ahc_reg_parse_entry_t SEQ_FLAGS2_parse_table[] = {
{ "SCB_DMA", 0x01, 0x01 },
{ "TARGET_MSG_PENDING", 0x02, 0x02 }
};
@ -770,7 +714,7 @@ ahc_seq_flags2_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x57, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SCSICONF_parse_table[] = {
static const ahc_reg_parse_entry_t SCSICONF_parse_table[] = {
{ "ENSPCHK", 0x20, 0x20 },
{ "RESET_SCSI", 0x40, 0x40 },
{ "TERM_ENB", 0x80, 0x80 },
@ -785,7 +729,7 @@ ahc_scsiconf_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x5a, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t INTDEF_parse_table[] = {
static const ahc_reg_parse_entry_t INTDEF_parse_table[] = {
{ "EDGE_TRIG", 0x80, 0x80 },
{ "VECTOR", 0x0f, 0x0f }
};
@ -804,7 +748,7 @@ ahc_hostconf_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x5d, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t HA_274_BIOSCTRL_parse_table[] = {
static const ahc_reg_parse_entry_t HA_274_BIOSCTRL_parse_table[] = {
{ "CHANNEL_B_PRIMARY", 0x08, 0x08 },
{ "BIOSMODE", 0x30, 0x30 },
{ "BIOSDISABLED", 0x30, 0x30 }
@ -817,7 +761,7 @@ ahc_ha_274_biosctrl_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x5f, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SEQCTL_parse_table[] = {
static const ahc_reg_parse_entry_t SEQCTL_parse_table[] = {
{ "LOADRAM", 0x01, 0x01 },
{ "SEQRESET", 0x02, 0x02 },
{ "STEP", 0x04, 0x04 },
@ -849,7 +793,7 @@ ahc_seqaddr0_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x62, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SEQADDR1_parse_table[] = {
static const ahc_reg_parse_entry_t SEQADDR1_parse_table[] = {
{ "SEQADDR1_MASK", 0x01, 0x01 }
};
@ -902,7 +846,7 @@ ahc_none_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x6a, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t FLAGS_parse_table[] = {
static const ahc_reg_parse_entry_t FLAGS_parse_table[] = {
{ "CARRY", 0x01, 0x01 },
{ "ZERO", 0x02, 0x02 }
};
@ -928,13 +872,6 @@ ahc_dindir_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x6d, regvalue, cur_col, wrap));
}
int
ahc_function1_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahc_print_register(NULL, 0, "FUNCTION1",
0x6e, regvalue, cur_col, wrap));
}
int
ahc_stack_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
@ -956,19 +893,7 @@ ahc_sram_base_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x70, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t BCTL_parse_table[] = {
{ "ENABLE", 0x01, 0x01 },
{ "ACE", 0x08, 0x08 }
};
int
ahc_bctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahc_print_register(BCTL_parse_table, 2, "BCTL",
0x84, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t DSCOMMAND0_parse_table[] = {
static const ahc_reg_parse_entry_t DSCOMMAND0_parse_table[] = {
{ "CIOPARCKEN", 0x01, 0x01 },
{ "USCBSIZE32", 0x02, 0x02 },
{ "RAMPS", 0x04, 0x04 },
@ -986,7 +911,7 @@ ahc_dscommand0_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x84, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t BUSTIME_parse_table[] = {
static const ahc_reg_parse_entry_t BUSTIME_parse_table[] = {
{ "BON", 0x0f, 0x0f },
{ "BOFF", 0xf0, 0xf0 }
};
@ -998,7 +923,7 @@ ahc_bustime_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x85, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t DSCOMMAND1_parse_table[] = {
static const ahc_reg_parse_entry_t DSCOMMAND1_parse_table[] = {
{ "HADDLDSEL0", 0x01, 0x01 },
{ "HADDLDSEL1", 0x02, 0x02 },
{ "DSLATT", 0xfc, 0xfc }
@ -1011,7 +936,7 @@ ahc_dscommand1_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x85, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t BUSSPD_parse_table[] = {
static const ahc_reg_parse_entry_t BUSSPD_parse_table[] = {
{ "STBON", 0x07, 0x07 },
{ "STBOFF", 0x38, 0x38 },
{ "DFTHRSH_75", 0x80, 0x80 },
@ -1026,7 +951,7 @@ ahc_busspd_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x86, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t HS_MAILBOX_parse_table[] = {
static const ahc_reg_parse_entry_t HS_MAILBOX_parse_table[] = {
{ "SEQ_MAILBOX", 0x0f, 0x0f },
{ "HOST_TQINPOS", 0x80, 0x80 },
{ "HOST_MAILBOX", 0xf0, 0xf0 }
@ -1039,7 +964,7 @@ ahc_hs_mailbox_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x86, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t DSPCISTATUS_parse_table[] = {
static const ahc_reg_parse_entry_t DSPCISTATUS_parse_table[] = {
{ "DFTHRSH_100", 0xc0, 0xc0 }
};
@ -1050,7 +975,7 @@ ahc_dspcistatus_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x86, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t HCNTRL_parse_table[] = {
static const ahc_reg_parse_entry_t HCNTRL_parse_table[] = {
{ "CHIPRST", 0x01, 0x01 },
{ "CHIPRSTACK", 0x01, 0x01 },
{ "INTEN", 0x02, 0x02 },
@ -1088,7 +1013,7 @@ ahc_scbptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x90, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t INTSTAT_parse_table[] = {
static const ahc_reg_parse_entry_t INTSTAT_parse_table[] = {
{ "SEQINT", 0x01, 0x01 },
{ "CMDCMPLT", 0x02, 0x02 },
{ "SCSIINT", 0x04, 0x04 },
@ -1119,7 +1044,7 @@ ahc_intstat_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x91, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t CLRINT_parse_table[] = {
static const ahc_reg_parse_entry_t CLRINT_parse_table[] = {
{ "CLRSEQINT", 0x01, 0x01 },
{ "CLRCMDINT", 0x02, 0x02 },
{ "CLRSCSIINT", 0x04, 0x04 },
@ -1134,7 +1059,7 @@ ahc_clrint_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x92, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t ERROR_parse_table[] = {
static const ahc_reg_parse_entry_t ERROR_parse_table[] = {
{ "ILLHADDR", 0x01, 0x01 },
{ "ILLSADDR", 0x02, 0x02 },
{ "ILLOPCODE", 0x04, 0x04 },
@ -1152,7 +1077,7 @@ ahc_error_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x92, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t DFCNTRL_parse_table[] = {
static const ahc_reg_parse_entry_t DFCNTRL_parse_table[] = {
{ "FIFORESET", 0x01, 0x01 },
{ "FIFOFLUSH", 0x02, 0x02 },
{ "DIRECTION", 0x04, 0x04 },
@ -1172,7 +1097,7 @@ ahc_dfcntrl_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x93, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t DFSTATUS_parse_table[] = {
static const ahc_reg_parse_entry_t DFSTATUS_parse_table[] = {
{ "FIFOEMP", 0x01, 0x01 },
{ "FIFOFULL", 0x02, 0x02 },
{ "DFTHRESH", 0x04, 0x04 },
@ -1197,13 +1122,6 @@ ahc_dfwaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x95, regvalue, cur_col, wrap));
}
int
ahc_dfraddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahc_print_register(NULL, 0, "DFRADDR",
0x97, regvalue, cur_col, wrap));
}
int
ahc_dfdat_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
@ -1211,7 +1129,7 @@ ahc_dfdat_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x99, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SCBCNT_parse_table[] = {
static const ahc_reg_parse_entry_t SCBCNT_parse_table[] = {
{ "SCBAUTO", 0x80, 0x80 },
{ "SCBCNT_MASK", 0x1f, 0x1f }
};
@ -1230,13 +1148,6 @@ ahc_qinfifo_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x9b, regvalue, cur_col, wrap));
}
int
ahc_qincnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahc_print_register(NULL, 0, "QINCNT",
0x9c, regvalue, cur_col, wrap));
}
int
ahc_qoutfifo_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
@ -1244,7 +1155,7 @@ ahc_qoutfifo_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x9d, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t CRCCONTROL1_parse_table[] = {
static const ahc_reg_parse_entry_t CRCCONTROL1_parse_table[] = {
{ "TARGCRCCNTEN", 0x04, 0x04 },
{ "TARGCRCENDEN", 0x08, 0x08 },
{ "CRCREQCHKEN", 0x10, 0x10 },
@ -1260,14 +1171,7 @@ ahc_crccontrol1_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x9d, regvalue, cur_col, wrap));
}
int
ahc_qoutcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahc_print_register(NULL, 0, "QOUTCNT",
0x9e, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SCSIPHASE_parse_table[] = {
static const ahc_reg_parse_entry_t SCSIPHASE_parse_table[] = {
{ "DATA_OUT_PHASE", 0x01, 0x01 },
{ "DATA_IN_PHASE", 0x02, 0x02 },
{ "MSG_OUT_PHASE", 0x04, 0x04 },
@ -1284,7 +1188,7 @@ ahc_scsiphase_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x9e, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SFUNCT_parse_table[] = {
static const ahc_reg_parse_entry_t SFUNCT_parse_table[] = {
{ "ALT_MODE", 0x80, 0x80 }
};
@ -1351,7 +1255,7 @@ ahc_scb_dataptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
0xac, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SCB_DATACNT_parse_table[] = {
static const ahc_reg_parse_entry_t SCB_DATACNT_parse_table[] = {
{ "SG_LAST_SEG", 0x80, 0x80 },
{ "SG_HIGH_ADDR_BITS", 0x7f, 0x7f }
};
@ -1363,7 +1267,7 @@ ahc_scb_datacnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
0xb0, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SCB_SGPTR_parse_table[] = {
static const ahc_reg_parse_entry_t SCB_SGPTR_parse_table[] = {
{ "SG_LIST_NULL", 0x01, 0x01 },
{ "SG_FULL_RESID", 0x02, 0x02 },
{ "SG_RESID_VALID", 0x04, 0x04 }
@ -1376,7 +1280,7 @@ ahc_scb_sgptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
0xb4, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SCB_CONTROL_parse_table[] = {
static const ahc_reg_parse_entry_t SCB_CONTROL_parse_table[] = {
{ "DISCONNECTED", 0x04, 0x04 },
{ "ULTRAENB", 0x08, 0x08 },
{ "MK_MESSAGE", 0x10, 0x10 },
@ -1394,7 +1298,7 @@ ahc_scb_control_print(u_int regvalue, u_int *cur_col, u_int wrap)
0xb8, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SCB_SCSIID_parse_table[] = {
static const ahc_reg_parse_entry_t SCB_SCSIID_parse_table[] = {
{ "TWIN_CHNLB", 0x80, 0x80 },
{ "OID", 0x0f, 0x0f },
{ "TWIN_TID", 0x70, 0x70 },
@ -1408,7 +1312,7 @@ ahc_scb_scsiid_print(u_int regvalue, u_int *cur_col, u_int wrap)
0xb9, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SCB_LUN_parse_table[] = {
static const ahc_reg_parse_entry_t SCB_LUN_parse_table[] = {
{ "SCB_XFERLEN_ODD", 0x80, 0x80 },
{ "LID", 0x3f, 0x3f }
};
@ -1455,14 +1359,7 @@ ahc_scb_next_print(u_int regvalue, u_int *cur_col, u_int wrap)
0xbf, regvalue, cur_col, wrap));
}
int
ahc_scb_64_spare_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahc_print_register(NULL, 0, "SCB_64_SPARE",
0xc0, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SEECTL_2840_parse_table[] = {
static const ahc_reg_parse_entry_t SEECTL_2840_parse_table[] = {
{ "DO_2840", 0x01, 0x01 },
{ "CK_2840", 0x02, 0x02 },
{ "CS_2840", 0x04, 0x04 }
@ -1475,7 +1372,7 @@ ahc_seectl_2840_print(u_int regvalue, u_int *cur_col, u_int wrap)
0xc0, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t STATUS_2840_parse_table[] = {
static const ahc_reg_parse_entry_t STATUS_2840_parse_table[] = {
{ "DI_2840", 0x01, 0x01 },
{ "EEPROM_TF", 0x80, 0x80 },
{ "ADSEL", 0x1e, 0x1e },
@ -1524,7 +1421,7 @@ ahc_ccsgaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
0xea, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t CCSGCTL_parse_table[] = {
static const ahc_reg_parse_entry_t CCSGCTL_parse_table[] = {
{ "CCSGRESET", 0x01, 0x01 },
{ "SG_FETCH_NEEDED", 0x02, 0x02 },
{ "CCSGEN", 0x08, 0x08 },
@ -1552,7 +1449,7 @@ ahc_ccscbaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
0xed, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t CCSCBCTL_parse_table[] = {
static const ahc_reg_parse_entry_t CCSCBCTL_parse_table[] = {
{ "CCSCBRESET", 0x01, 0x01 },
{ "CCSCBDIR", 0x04, 0x04 },
{ "CCSCBEN", 0x08, 0x08 },
@ -1610,7 +1507,7 @@ ahc_sdscb_qoff_print(u_int regvalue, u_int *cur_col, u_int wrap)
0xf8, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t QOFF_CTLSTA_parse_table[] = {
static const ahc_reg_parse_entry_t QOFF_CTLSTA_parse_table[] = {
{ "SDSCB_ROLLOVER", 0x10, 0x10 },
{ "SNSCB_ROLLOVER", 0x20, 0x20 },
{ "SCB_AVAIL", 0x40, 0x40 },
@ -1625,7 +1522,7 @@ ahc_qoff_ctlsta_print(u_int regvalue, u_int *cur_col, u_int wrap)
0xfa, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t DFF_THRSH_parse_table[] = {
static const ahc_reg_parse_entry_t DFF_THRSH_parse_table[] = {
{ "RD_DFTHRSH_MIN", 0x00, 0x00 },
{ "WR_DFTHRSH_MIN", 0x00, 0x00 },
{ "RD_DFTHRSH_25", 0x01, 0x01 },
@ -1653,7 +1550,7 @@ ahc_dff_thrsh_print(u_int regvalue, u_int *cur_col, u_int wrap)
0xfb, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SG_CACHE_SHADOW_parse_table[] = {
static const ahc_reg_parse_entry_t SG_CACHE_SHADOW_parse_table[] = {
{ "LAST_SEG_DONE", 0x01, 0x01 },
{ "LAST_SEG", 0x02, 0x02 },
{ "SG_ADDR_MASK", 0xf8, 0xf8 }
@ -1666,7 +1563,7 @@ ahc_sg_cache_shadow_print(u_int regvalue, u_int *cur_col, u_int wrap)
0xfc, regvalue, cur_col, wrap));
}
static ahc_reg_parse_entry_t SG_CACHE_PRE_parse_table[] = {
static const ahc_reg_parse_entry_t SG_CACHE_PRE_parse_table[] = {
{ "LAST_SEG_DONE", 0x01, 0x01 },
{ "LAST_SEG", 0x02, 0x02 },
{ "SG_ADDR_MASK", 0xf8, 0xf8 }

View File

@ -5,7 +5,7 @@
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#58 $
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#40 $
*/
static uint8_t seqprog[] = {
static const uint8_t seqprog[] = {
0xb2, 0x00, 0x00, 0x08,
0xf7, 0x11, 0x22, 0x08,
0x00, 0x65, 0xee, 0x59,
@ -1081,7 +1081,7 @@ ahc_patch0_func(struct ahc_softc *ahc)
return (0);
}
static struct patch {
static const struct patch {
ahc_patch_func_t *patch_func;
uint32_t begin :10,
skip_instr :10,
@ -1291,7 +1291,7 @@ static struct patch {
{ ahc_patch4_func, 865, 12, 1 }
};
static struct cs {
static const struct cs {
uint16_t begin;
uint16_t end;
} critical_sections[] = {

View File

@ -362,7 +362,7 @@ output_code()
" *\n"
"%s */\n", versions);
fprintf(ofile, "static uint8_t seqprog[] = {\n");
fprintf(ofile, "static const uint8_t seqprog[] = {\n");
for (cur_instr = STAILQ_FIRST(&seq_program);
cur_instr != NULL;
cur_instr = STAILQ_NEXT(cur_instr, links)) {
@ -415,7 +415,7 @@ output_code()
}
fprintf(ofile,
"static struct patch {\n"
"static const struct patch {\n"
" %spatch_func_t *patch_func;\n"
" uint32_t begin :10,\n"
" skip_instr :10,\n"
@ -435,7 +435,7 @@ output_code()
fprintf(ofile, "\n};\n\n");
fprintf(ofile,
"static struct cs {\n"
"static const struct cs {\n"
" uint16_t begin;\n"
" uint16_t end;\n"
"} critical_sections[] = {\n");

View File

@ -101,11 +101,12 @@ static void format_3_instr(int opcode, symbol_ref_t *src,
expression_t *immed, symbol_ref_t *address);
static void test_readable_symbol(symbol_t *symbol);
static void test_writable_symbol(symbol_t *symbol);
static void type_check(symbol_t *symbol, expression_t *expression, int and_op);
static void type_check(symbol_ref_t *sym, expression_t *expression, int and_op);
static void make_expression(expression_t *immed, int value);
static void add_conditional(symbol_t *symbol);
static void add_version(const char *verstring);
static int is_download_const(expression_t *immed);
static int is_location_address(symbol_t *symbol);
void yyerror(const char *string);
#define SRAM_SYMNAME "SRAM_BASE"
@ -142,6 +143,8 @@ void yyerror(const char *string);
%token <value> T_ADDRESS
%token T_COUNT
%token T_ACCESS_MODE
%token T_MODES
@ -192,10 +195,10 @@ void yyerror(const char *string);
%token <value> T_OR
/* 16 bit extensions */
%token <value> T_OR16 T_AND16 T_XOR16 T_ADD16
%token <value> T_ADC16 T_MVI16 T_TEST16 T_CMP16 T_CMPXCHG
/* 16 bit extensions, not implemented
* %token <value> T_OR16 T_AND16 T_XOR16 T_ADD16
* %token <value> T_ADC16 T_MVI16 T_TEST16 T_CMP16 T_CMPXCHG
*/
%token T_RET
%token T_NOP
@ -214,7 +217,7 @@ void yyerror(const char *string);
%type <expression> expression immediate immediate_or_a
%type <value> export ret f1_opcode f2_opcode f4_opcode jmp_jc_jnc_call jz_jnz je_jne
%type <value> export ret f1_opcode f2_opcode jmp_jc_jnc_call jz_jnz je_jne
%type <value> mode_value mode_list macro_arglist
@ -313,13 +316,13 @@ reg_definition:
stop("Register multiply defined", EX_DATAERR);
/* NOTREACHED */
}
cur_symbol = $1;
cur_symbol = $1;
cur_symbol->type = cur_symtype;
initialize_symbol(cur_symbol);
}
reg_attribute_list
'}'
{
{
/*
* Default to allowing everything in for registers
* with no bit or mask definitions.
@ -349,9 +352,10 @@ reg_attribute_list:
| reg_attribute_list reg_attribute
;
reg_attribute:
reg_attribute:
reg_address
| size
| count
| access_mode
| modes
| field_defn
@ -392,6 +396,13 @@ size:
}
;
count:
T_COUNT T_NUMBER
{
cur_symbol->count += $2;
}
;
access_mode:
T_ACCESS_MODE T_MODE
{
@ -641,14 +652,14 @@ expression:
&($1.referenced_syms),
&($3.referenced_syms));
}
| expression T_EXPR_LSHIFT expression
| expression T_EXPR_LSHIFT expression
{
$$.value = $1.value << $3.value;
symlist_merge(&$$.referenced_syms,
&$1.referenced_syms,
&$3.referenced_syms);
}
| expression T_EXPR_RSHIFT expression
| expression T_EXPR_RSHIFT expression
{
$$.value = $1.value >> $3.value;
symlist_merge(&$$.referenced_syms,
@ -714,7 +725,7 @@ expression:
;
constant:
T_CONST T_SYMBOL expression
T_CONST T_SYMBOL expression
{
if ($2->type != UNINITIALIZED) {
stop("Re-definition of symbol as a constant",
@ -800,6 +811,7 @@ scratch_ram:
cur_symtype = SRAMLOC;
cur_symbol->type = SRAMLOC;
initialize_symbol(cur_symbol);
cur_symbol->count += 1;
}
reg_address
{
@ -831,6 +843,7 @@ scb:
initialize_symbol(cur_symbol);
/* 64 bytes of SCB space */
cur_symbol->info.rinfo->size = 64;
cur_symbol->count += 1;
}
reg_address
{
@ -1311,14 +1324,18 @@ f2_opcode:
| T_ROR { $$ = AIC_OP_ROR; }
;
f4_opcode:
T_OR16 { $$ = AIC_OP_OR16; }
| T_AND16 { $$ = AIC_OP_AND16; }
| T_XOR16 { $$ = AIC_OP_XOR16; }
| T_ADD16 { $$ = AIC_OP_ADD16; }
| T_ADC16 { $$ = AIC_OP_ADC16; }
| T_MVI16 { $$ = AIC_OP_MVI16; }
;
/*
* 16bit opcodes, not used
*
*f4_opcode:
* T_OR16 { $$ = AIC_OP_OR16; }
*| T_AND16 { $$ = AIC_OP_AND16; }
*| T_XOR16 { $$ = AIC_OP_XOR16; }
*| T_ADD16 { $$ = AIC_OP_ADD16; }
*| T_ADC16 { $$ = AIC_OP_ADC16; }
*| T_MVI16 { $$ = AIC_OP_MVI16; }
*;
*/
code:
f2_opcode destination ',' expression opt_source ret ';'
@ -1357,6 +1374,7 @@ code:
code:
T_OR reg_symbol ',' immediate jmp_jc_jnc_call address ';'
{
type_check(&$2, &$4, AIC_OP_OR);
format_3_instr($5, &$2, &$4, &$6);
}
;
@ -1528,7 +1546,7 @@ initialize_symbol(symbol_t *symbol)
sizeof(struct cond_info));
break;
case MACRO:
symbol->info.macroinfo =
symbol->info.macroinfo =
(struct macro_info *)malloc(sizeof(struct macro_info));
if (symbol->info.macroinfo == NULL) {
stop("Can't create macro info", EX_SOFTWARE);
@ -1552,7 +1570,6 @@ add_macro_arg(const char *argtext, int argnum)
struct macro_arg *marg;
int i;
int retval;
if (cur_symbol == NULL || cur_symbol->type != MACRO) {
stop("Invalid current symbol for adding macro arg",
@ -1633,8 +1650,10 @@ format_1_instr(int opcode, symbol_ref_t *dest, expression_t *immed,
test_writable_symbol(dest->symbol);
test_readable_symbol(src->symbol);
/* Ensure that immediate makes sense for this destination */
type_check(dest->symbol, immed, opcode);
if (!is_location_address(dest->symbol)) {
/* Ensure that immediate makes sense for this destination */
type_check(dest, immed, opcode);
}
/* Allocate sequencer space for the instruction and fill it out */
instr = seq_alloc();
@ -1766,9 +1785,6 @@ format_3_instr(int opcode, symbol_ref_t *src,
/* Test register permissions */
test_readable_symbol(src->symbol);
/* Ensure that immediate makes sense for this source */
type_check(src->symbol, immed, opcode);
/* Allocate sequencer space for the instruction and fill it out */
instr = seq_alloc();
f3_instr = &instr->format.format3;
@ -1797,7 +1813,6 @@ format_3_instr(int opcode, symbol_ref_t *src,
static void
test_readable_symbol(symbol_t *symbol)
{
if ((symbol->info.rinfo->modes & (0x1 << src_mode)) == 0) {
snprintf(errbuf, sizeof(errbuf),
"Register %s unavailable in source reg mode %d",
@ -1815,7 +1830,6 @@ test_readable_symbol(symbol_t *symbol)
static void
test_writable_symbol(symbol_t *symbol)
{
if ((symbol->info.rinfo->modes & (0x1 << dst_mode)) == 0) {
snprintf(errbuf, sizeof(errbuf),
"Register %s unavailable in destination reg mode %d",
@ -1831,25 +1845,34 @@ test_writable_symbol(symbol_t *symbol)
}
static void
type_check(symbol_t *symbol, expression_t *expression, int opcode)
type_check(symbol_ref_t *sym, expression_t *expression, int opcode)
{
symbol_t *symbol = sym->symbol;
symbol_node_t *node;
int and_op;
int8_t value, mask;
and_op = FALSE;
if (opcode == AIC_OP_AND || opcode == AIC_OP_JNZ || opcode == AIC_OP_JZ)
and_op = TRUE;
/*
* Make sure that we aren't attempting to write something
* that hasn't been defined. If this is an and operation,
* this is a mask, so "undefined" bits are okay.
*/
if (and_op == FALSE
&& (expression->value & ~symbol->info.rinfo->valid_bitmask) != 0) {
if (opcode == AIC_OP_AND || opcode == AIC_OP_JNZ ||
opcode == AIC_OP_JZ || opcode == AIC_OP_JNE ||
opcode == AIC_OP_BMOV)
and_op = TRUE;
/*
* Defaulting to 8 bit logic
*/
mask = (int8_t)~symbol->info.rinfo->valid_bitmask;
value = (int8_t)expression->value;
if (and_op == FALSE && (mask & value) != 0 ) {
snprintf(errbuf, sizeof(errbuf),
"Invalid bit(s) 0x%x in immediate written to %s",
expression->value & ~symbol->info.rinfo->valid_bitmask,
(mask & value),
symbol->name);
stop(errbuf, EX_DATAERR);
/* NOTREACHED */
@ -1959,3 +1982,13 @@ is_download_const(expression_t *immed)
return (FALSE);
}
static int
is_location_address(symbol_t *sym)
{
if (sym->type == SCBLOC ||
sym->type == SRAMLOC)
return (TRUE);
return (FALSE);
}

View File

@ -162,6 +162,7 @@ register { return T_REGISTER; }
const { yylval.value = FALSE; return T_CONST; }
download { return T_DOWNLOAD; }
address { return T_ADDRESS; }
count { return T_COUNT; }
access_mode { return T_ACCESS_MODE; }
modes { return T_MODES; }
RW|RO|WO {
@ -228,15 +229,15 @@ ret { return T_RET; }
nop { return T_NOP; }
/* ARP2 16bit extensions */
or16 { return T_OR16; }
and16 { return T_AND16; }
xor16 { return T_XOR16; }
add16 { return T_ADD16; }
adc16 { return T_ADC16; }
mvi16 { return T_MVI16; }
test16 { return T_TEST16; }
cmp16 { return T_CMP16; }
cmpxchg { return T_CMPXCHG; }
/* or16 { return T_OR16; } */
/* and16 { return T_AND16; }*/
/* xor16 { return T_XOR16; }*/
/* add16 { return T_ADD16; }*/
/* adc16 { return T_ADC16; }*/
/* mvi16 { return T_MVI16; }*/
/* test16 { return T_TEST16; }*/
/* cmp16 { return T_CMP16; }*/
/* cmpxchg { return T_CMPXCHG; }*/
/* Allowed Symbols */
\<\< { return T_EXPR_LSHIFT; }

View File

@ -77,6 +77,7 @@ symbol_create(char *name)
if (new_symbol->name == NULL)
stop("Unable to strdup symbol name", EX_SOFTWARE);
new_symbol->type = UNINITIALIZED;
new_symbol->count = 1;
return (new_symbol);
}
@ -198,6 +199,12 @@ symtable_get(char *name)
}
}
memcpy(&stored_ptr, data.data, sizeof(stored_ptr));
stored_ptr->count++;
data.data = &stored_ptr;
if (symtable->put(symtable, &key, &data, /*flags*/0) !=0) {
perror("Symtable put failed");
exit(EX_SOFTWARE);
}
return (stored_ptr);
}
@ -256,7 +263,7 @@ symlist_add(symlist_t *symlist, symbol_t *symbol, int how)
&& (curnode->symbol->info.finfo->value >
newnode->symbol->info.finfo->value))))
|| (!field && (curnode->symbol->info.rinfo->address >
newnode->symbol->info.rinfo->address))) {
newnode->symbol->info.rinfo->address))) {
SLIST_INSERT_HEAD(symlist, newnode, links);
return;
}
@ -271,7 +278,7 @@ symlist_add(symlist_t *symlist, symbol_t *symbol, int how)
cursymbol = SLIST_NEXT(curnode, links)->symbol;
if ((field
&& (cursymbol->type > symbol->type
&& (cursymbol->type > symbol->type
|| (cursymbol->type == symbol->type
&& (cursymbol->info.finfo->value >
symbol->info.finfo->value))))
@ -351,7 +358,7 @@ aic_print_reg_dump_types(FILE *ofile)
{
if (ofile == NULL)
return;
fprintf(ofile,
"typedef int (%sreg_print_t)(u_int, u_int *, u_int);\n"
"typedef struct %sreg_parse_entry {\n"
@ -370,7 +377,7 @@ aic_print_reg_dump_start(FILE *dfile, symbol_node_t *regnode)
return;
fprintf(dfile,
"static %sreg_parse_entry_t %s_parse_table[] = {\n",
"static const %sreg_parse_entry_t %s_parse_table[] = {\n",
prefix,
regnode->symbol->name);
}
@ -385,7 +392,7 @@ aic_print_reg_dump_end(FILE *ofile, FILE *dfile,
lower_name = strdup(regnode->symbol->name);
if (lower_name == NULL)
stop("Unable to strdup symbol name", EX_SOFTWARE);
for (letter = lower_name; *letter != '\0'; letter++)
*letter = tolower(*letter);
@ -472,6 +479,7 @@ symtable_dump(FILE *ofile, FILE *dfile)
DBT key;
DBT data;
int flag;
int reg_count = 0, reg_used = 0;
u_int i;
if (symtable == NULL)
@ -541,6 +549,9 @@ symtable_dump(FILE *ofile, FILE *dfile)
int num_entries;
num_entries = 0;
reg_count++;
if (curnode->symbol->count == 1)
break;
fields = &curnode->symbol->info.rinfo->fields;
SLIST_FOREACH(fieldnode, fields, links) {
if (num_entries == 0)
@ -553,11 +564,14 @@ symtable_dump(FILE *ofile, FILE *dfile)
}
aic_print_reg_dump_end(ofile, dfile,
curnode, num_entries);
reg_used++;
}
default:
break;
}
}
fprintf(stderr, "%s: %d of %d register definitions used\n", appname,
reg_used, reg_count);
/* Fold in the masks and bits */
while (SLIST_FIRST(&masks) != NULL) {
@ -646,7 +660,6 @@ symtable_dump(FILE *ofile, FILE *dfile)
free(curnode);
}
fprintf(ofile, "\n\n/* Downloaded Constant Definitions */\n");
for (i = 0; SLIST_FIRST(&download_constants) != NULL; i++) {

View File

@ -128,6 +128,7 @@ typedef struct expression_info {
typedef struct symbol {
char *name;
symtype type;
int count;
union {
struct reg_info *rinfo;
struct field_info *finfo;

View File

@ -2286,17 +2286,14 @@ static void flush_dev(struct scsi_device *dev, unsigned long cursec,
}
}
static irqreturn_t ihdlr(int irq, struct Scsi_Host *shost)
static irqreturn_t ihdlr(struct Scsi_Host *shost)
{
struct scsi_cmnd *SCpnt;
unsigned int i, k, c, status, tstatus, reg;
struct mssp *spp;
struct mscp *cpp;
struct hostdata *ha = (struct hostdata *)shost->hostdata;
if (shost->irq != irq)
panic("%s: ihdlr, irq %d, shost->irq %d.\n", ha->board_name, irq,
shost->irq);
int irq = shost->irq;
/* Check if this board need to be serviced */
if (!(inb(shost->io_port + REG_AUX_STATUS) & IRQ_ASSERTED))
@ -2535,7 +2532,7 @@ static irqreturn_t ihdlr(int irq, struct Scsi_Host *shost)
return IRQ_NONE;
}
static irqreturn_t do_interrupt_handler(int irq, void *shap)
static irqreturn_t do_interrupt_handler(int dummy, void *shap)
{
struct Scsi_Host *shost;
unsigned int j;
@ -2548,7 +2545,7 @@ static irqreturn_t do_interrupt_handler(int irq, void *shap)
shost = sh[j];
spin_lock_irqsave(shost->host_lock, spin_flags);
ret = ihdlr(irq, shost);
ret = ihdlr(shost);
spin_unlock_irqrestore(shost->host_lock, spin_flags);
return ret;
}

View File

@ -978,7 +978,7 @@ static int esp_check_spur_intr(struct esp *esp)
*/
if (!esp->ops->dma_error(esp)) {
printk(KERN_ERR PFX "esp%d: Spurious irq, "
"sreg=%x.\n",
"sreg=%02x.\n",
esp->host->unique_id, esp->sreg);
return -1;
}
@ -1447,6 +1447,9 @@ static void esp_msgin_sdtr(struct esp *esp, struct esp_target_data *tp)
if (offset > 15)
goto do_reject;
if (esp->flags & ESP_FLAG_DISABLE_SYNC)
offset = 0;
if (offset) {
int rounded_up, one_clock;
@ -1697,7 +1700,12 @@ again:
else
ent->flags &= ~ESP_CMD_FLAG_WRITE;
dma_len = esp_dma_length_limit(esp, dma_addr, dma_len);
if (esp->ops->dma_length_limit)
dma_len = esp->ops->dma_length_limit(esp, dma_addr,
dma_len);
else
dma_len = esp_dma_length_limit(esp, dma_addr, dma_len);
esp->data_dma_len = dma_len;
if (!dma_len) {
@ -1761,7 +1769,6 @@ again:
esp_advance_dma(esp, ent, cmd, bytes_sent);
esp_event(esp, ESP_EVENT_CHECK_PHASE);
goto again;
break;
}
case ESP_EVENT_STATUS: {
@ -2235,7 +2242,7 @@ static void esp_bootup_reset(struct esp *esp)
static void esp_set_clock_params(struct esp *esp)
{
int fmhz;
int fhz;
u8 ccf;
/* This is getting messy but it has to be done correctly or else
@ -2270,9 +2277,9 @@ static void esp_set_clock_params(struct esp *esp)
* This entails the smallest and largest sync period we could ever
* handle on this ESP.
*/
fmhz = esp->cfreq;
fhz = esp->cfreq;
ccf = ((fmhz / 1000000) + 4) / 5;
ccf = ((fhz / 1000000) + 4) / 5;
if (ccf == 1)
ccf = 2;
@ -2281,16 +2288,16 @@ static void esp_set_clock_params(struct esp *esp)
* been unable to find the clock-frequency PROM property. All
* other machines provide useful values it seems.
*/
if (fmhz <= 5000000 || ccf < 1 || ccf > 8) {
fmhz = 20000000;
if (fhz <= 5000000 || ccf < 1 || ccf > 8) {
fhz = 20000000;
ccf = 4;
}
esp->cfact = (ccf == 8 ? 0 : ccf);
esp->cfreq = fmhz;
esp->ccycle = ESP_MHZ_TO_CYCLE(fmhz);
esp->cfreq = fhz;
esp->ccycle = ESP_HZ_TO_CYCLE(fhz);
esp->ctick = ESP_TICK(ccf, esp->ccycle);
esp->neg_defp = ESP_NEG_DEFP(fmhz, ccf);
esp->neg_defp = ESP_NEG_DEFP(fhz, ccf);
esp->sync_defp = SYNC_DEFP_SLOW;
}
@ -2382,6 +2389,12 @@ static int esp_slave_configure(struct scsi_device *dev)
struct esp_target_data *tp = &esp->target[dev->id];
int goal_tags, queue_depth;
if (esp->flags & ESP_FLAG_DISABLE_SYNC) {
/* Bypass async domain validation */
dev->ppr = 0;
dev->sdtr = 0;
}
goal_tags = 0;
if (dev->tagged_supported) {

View File

@ -224,7 +224,7 @@
#define ESP_TIMEO_CONST 8192
#define ESP_NEG_DEFP(mhz, cfact) \
((ESP_BUS_TIMEOUT * ((mhz) / 1000)) / (8192 * (cfact)))
#define ESP_MHZ_TO_CYCLE(mhertz) ((1000000000) / ((mhertz) / 1000))
#define ESP_HZ_TO_CYCLE(hertz) ((1000000000) / ((hertz) / 1000))
#define ESP_TICK(ccf, cycle) ((7682 * (ccf) * (cycle) / 1000))
/* For slow to medium speed input clock rates we shoot for 5mb/s, but for high
@ -240,9 +240,9 @@ struct esp_cmd_priv {
int num_sg;
} u;
unsigned int cur_residue;
int cur_residue;
struct scatterlist *cur_sg;
unsigned int tot_residue;
int tot_residue;
};
#define ESP_CMD_PRIV(CMD) ((struct esp_cmd_priv *)(&(CMD)->SCp))
@ -368,6 +368,12 @@ struct esp_driver_ops {
*/
int (*irq_pending)(struct esp *esp);
/* Return the maximum allowable size of a DMA transfer for a
* given buffer.
*/
u32 (*dma_length_limit)(struct esp *esp, u32 dma_addr,
u32 dma_len);
/* Reset the DMA engine entirely. On return, ESP interrupts
* should be enabled. Often the interrupt enabling is
* controlled in the DMA engine.
@ -471,6 +477,7 @@ struct esp {
#define ESP_FLAG_DOING_SLOWCMD 0x00000004
#define ESP_FLAG_WIDE_CAPABLE 0x00000008
#define ESP_FLAG_QUICKIRQ_CHECK 0x00000010
#define ESP_FLAG_DISABLE_SYNC 0x00000020
u8 select_state;
#define ESP_SELECT_NONE 0x00 /* Not selecting */

View File

@ -199,9 +199,13 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
if (!shost->can_queue) {
printk(KERN_ERR "%s: can_queue = 0 no longer supported\n",
sht->name);
goto out;
goto fail;
}
error = scsi_setup_command_freelist(shost);
if (error)
goto fail;
if (!shost->shost_gendev.parent)
shost->shost_gendev.parent = dev ? dev : &platform_bus;
@ -255,6 +259,8 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
out_del_gendev:
device_del(&shost->shost_gendev);
out:
scsi_destroy_command_freelist(shost);
fail:
return error;
}
EXPORT_SYMBOL(scsi_add_host);
@ -284,6 +290,11 @@ static void scsi_host_dev_release(struct device *dev)
kfree(shost);
}
struct device_type scsi_host_type = {
.name = "scsi_host",
.release = scsi_host_dev_release,
};
/**
* scsi_host_alloc - register a scsi host adapter instance.
* @sht: pointer to scsi host template
@ -376,33 +387,31 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
else
shost->dma_boundary = 0xffffffff;
rval = scsi_setup_command_freelist(shost);
if (rval)
goto fail_kfree;
device_initialize(&shost->shost_gendev);
snprintf(shost->shost_gendev.bus_id, BUS_ID_SIZE, "host%d",
shost->host_no);
shost->shost_gendev.release = scsi_host_dev_release;
#ifndef CONFIG_SYSFS_DEPRECATED
shost->shost_gendev.bus = &scsi_bus_type;
#endif
shost->shost_gendev.type = &scsi_host_type;
device_initialize(&shost->shost_dev);
shost->shost_dev.parent = &shost->shost_gendev;
shost->shost_dev.class = &shost_class;
snprintf(shost->shost_dev.bus_id, BUS_ID_SIZE, "host%d",
shost->host_no);
shost->shost_dev.groups = scsi_sysfs_shost_attr_groups;
shost->ehandler = kthread_run(scsi_error_handler, shost,
"scsi_eh_%d", shost->host_no);
if (IS_ERR(shost->ehandler)) {
rval = PTR_ERR(shost->ehandler);
goto fail_destroy_freelist;
goto fail_kfree;
}
scsi_proc_hostdir_add(shost->hostt);
return shost;
fail_destroy_freelist:
scsi_destroy_command_freelist(shost);
fail_kfree:
kfree(shost);
return NULL;
@ -496,7 +505,7 @@ void scsi_exit_hosts(void)
int scsi_is_host_device(const struct device *dev)
{
return dev->release == scsi_host_dev_release;
return dev->type == &scsi_host_type;
}
EXPORT_SYMBOL(scsi_is_host_device);

View File

@ -217,11 +217,15 @@ static int __devexit esp_jazz_remove(struct platform_device *dev)
return 0;
}
/* work with hotplug and coldplug */
MODULE_ALIAS("platform:jazz_esp");
static struct platform_driver esp_jazz_driver = {
.probe = esp_jazz_probe,
.remove = __devexit_p(esp_jazz_remove),
.driver = {
.name = "jazz_esp",
.owner = THIS_MODULE,
},
};

View File

@ -182,8 +182,8 @@ lpfc_option_rom_version_show(struct device *dev, struct device_attribute *attr,
return snprintf(buf, PAGE_SIZE, "%s\n", phba->OptionROMVersion);
}
static ssize_t
lpfc_state_show(struct device *dev, struct device_attribute *attr,
char *buf)
lpfc_link_state_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct Scsi_Host *shost = class_to_shost(dev);
struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
@ -936,7 +936,7 @@ static DEVICE_ATTR(programtype, S_IRUGO, lpfc_programtype_show, NULL);
static DEVICE_ATTR(portnum, S_IRUGO, lpfc_vportnum_show, NULL);
static DEVICE_ATTR(fwrev, S_IRUGO, lpfc_fwrev_show, NULL);
static DEVICE_ATTR(hdw, S_IRUGO, lpfc_hdw_show, NULL);
static DEVICE_ATTR(state, S_IRUGO, lpfc_state_show, NULL);
static DEVICE_ATTR(link_state, S_IRUGO, lpfc_link_state_show, NULL);
static DEVICE_ATTR(option_rom_version, S_IRUGO,
lpfc_option_rom_version_show, NULL);
static DEVICE_ATTR(num_discovered_ports, S_IRUGO,
@ -1666,7 +1666,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
&dev_attr_fwrev,
&dev_attr_hdw,
&dev_attr_option_rom_version,
&dev_attr_state,
&dev_attr_link_state,
&dev_attr_num_discovered_ports,
&dev_attr_lpfc_drvr_version,
&dev_attr_lpfc_temp_sensor,
@ -1714,7 +1714,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
struct device_attribute *lpfc_vport_attrs[] = {
&dev_attr_info,
&dev_attr_state,
&dev_attr_link_state,
&dev_attr_num_discovered_ports,
&dev_attr_lpfc_drvr_version,
&dev_attr_lpfc_log_verbose,

View File

@ -0,0 +1,657 @@
/* mac_esp.c: ESP front-end for Macintosh Quadra systems.
*
* Adapted from jazz_esp.c and the old mac_esp.c.
*
* The pseudo DMA algorithm is based on the one used in NetBSD.
* See sys/arch/mac68k/obio/esp.c for some background information.
*
* Copyright (C) 2007-2008 Finn Thain
*/
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/scatterlist.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/nubus.h>
#include <asm/irq.h>
#include <asm/dma.h>
#include <asm/macints.h>
#include <asm/macintosh.h>
#include <scsi/scsi_host.h>
#include "esp_scsi.h"
#define DRV_MODULE_NAME "mac_esp"
#define PFX DRV_MODULE_NAME ": "
#define DRV_VERSION "1.000"
#define DRV_MODULE_RELDATE "Sept 15, 2007"
#define MAC_ESP_IO_BASE 0x50F00000
#define MAC_ESP_REGS_QUADRA (MAC_ESP_IO_BASE + 0x10000)
#define MAC_ESP_REGS_QUADRA2 (MAC_ESP_IO_BASE + 0xF000)
#define MAC_ESP_REGS_QUADRA3 (MAC_ESP_IO_BASE + 0x18000)
#define MAC_ESP_REGS_SPACING 0x402
#define MAC_ESP_PDMA_REG 0xF9800024
#define MAC_ESP_PDMA_REG_SPACING 0x4
#define MAC_ESP_PDMA_IO_OFFSET 0x100
#define esp_read8(REG) mac_esp_read8(esp, REG)
#define esp_write8(VAL, REG) mac_esp_write8(esp, VAL, REG)
struct mac_esp_priv {
struct esp *esp;
void __iomem *pdma_regs;
void __iomem *pdma_io;
int error;
};
static struct platform_device *internal_esp, *external_esp;
#define MAC_ESP_GET_PRIV(esp) ((struct mac_esp_priv *) \
platform_get_drvdata((struct platform_device *) \
(esp->dev)))
static inline void mac_esp_write8(struct esp *esp, u8 val, unsigned long reg)
{
nubus_writeb(val, esp->regs + reg * 16);
}
static inline u8 mac_esp_read8(struct esp *esp, unsigned long reg)
{
return nubus_readb(esp->regs + reg * 16);
}
/* For pseudo DMA and PIO we need the virtual address
* so this address mapping is the identity mapping.
*/
static dma_addr_t mac_esp_map_single(struct esp *esp, void *buf,
size_t sz, int dir)
{
return (dma_addr_t)buf;
}
static int mac_esp_map_sg(struct esp *esp, struct scatterlist *sg,
int num_sg, int dir)
{
int i;
for (i = 0; i < num_sg; i++)
sg[i].dma_address = (u32)sg_virt(&sg[i]);
return num_sg;
}
static void mac_esp_unmap_single(struct esp *esp, dma_addr_t addr,
size_t sz, int dir)
{
/* Nothing to do. */
}
static void mac_esp_unmap_sg(struct esp *esp, struct scatterlist *sg,
int num_sg, int dir)
{
/* Nothing to do. */
}
static void mac_esp_reset_dma(struct esp *esp)
{
/* Nothing to do. */
}
static void mac_esp_dma_drain(struct esp *esp)
{
/* Nothing to do. */
}
static void mac_esp_dma_invalidate(struct esp *esp)
{
/* Nothing to do. */
}
static int mac_esp_dma_error(struct esp *esp)
{
return MAC_ESP_GET_PRIV(esp)->error;
}
static inline int mac_esp_wait_for_empty_fifo(struct esp *esp)
{
struct mac_esp_priv *mep = MAC_ESP_GET_PRIV(esp);
int i = 500000;
do {
if (!(esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES))
return 0;
if (esp_read8(ESP_STATUS) & ESP_STAT_INTR)
return 1;
udelay(2);
} while (--i);
printk(KERN_ERR PFX "FIFO is not empty (sreg %02x)\n",
esp_read8(ESP_STATUS));
mep->error = 1;
return 1;
}
static inline int mac_esp_wait_for_dreq(struct esp *esp)
{
struct mac_esp_priv *mep = MAC_ESP_GET_PRIV(esp);
int i = 500000;
do {
if (mep->pdma_regs == NULL) {
if (mac_irq_pending(IRQ_MAC_SCSIDRQ))
return 0;
} else {
if (nubus_readl(mep->pdma_regs) & 0x200)
return 0;
}
if (esp_read8(ESP_STATUS) & ESP_STAT_INTR)
return 1;
udelay(2);
} while (--i);
printk(KERN_ERR PFX "PDMA timeout (sreg %02x)\n",
esp_read8(ESP_STATUS));
mep->error = 1;
return 1;
}
#define MAC_ESP_PDMA_LOOP(operands) \
asm volatile ( \
" tstw %2 \n" \
" jbeq 20f \n" \
"1: movew " operands " \n" \
"2: movew " operands " \n" \
"3: movew " operands " \n" \
"4: movew " operands " \n" \
"5: movew " operands " \n" \
"6: movew " operands " \n" \
"7: movew " operands " \n" \
"8: movew " operands " \n" \
"9: movew " operands " \n" \
"10: movew " operands " \n" \
"11: movew " operands " \n" \
"12: movew " operands " \n" \
"13: movew " operands " \n" \
"14: movew " operands " \n" \
"15: movew " operands " \n" \
"16: movew " operands " \n" \
" subqw #1,%2 \n" \
" jbne 1b \n" \
"20: tstw %3 \n" \
" jbeq 30f \n" \
"21: movew " operands " \n" \
" subqw #1,%3 \n" \
" jbne 21b \n" \
"30: tstw %4 \n" \
" jbeq 40f \n" \
"31: moveb " operands " \n" \
"32: nop \n" \
"40: \n" \
" \n" \
" .section __ex_table,\"a\" \n" \
" .align 4 \n" \
" .long 1b,40b \n" \
" .long 2b,40b \n" \
" .long 3b,40b \n" \
" .long 4b,40b \n" \
" .long 5b,40b \n" \
" .long 6b,40b \n" \
" .long 7b,40b \n" \
" .long 8b,40b \n" \
" .long 9b,40b \n" \
" .long 10b,40b \n" \
" .long 11b,40b \n" \
" .long 12b,40b \n" \
" .long 13b,40b \n" \
" .long 14b,40b \n" \
" .long 15b,40b \n" \
" .long 16b,40b \n" \
" .long 21b,40b \n" \
" .long 31b,40b \n" \
" .long 32b,40b \n" \
" .previous \n" \
: "+a" (addr) \
: "a" (mep->pdma_io), "r" (count32), "r" (count2), "g" (esp_count))
static void mac_esp_send_pdma_cmd(struct esp *esp, u32 addr, u32 esp_count,
u32 dma_count, int write, u8 cmd)
{
struct mac_esp_priv *mep = MAC_ESP_GET_PRIV(esp);
unsigned long flags;
local_irq_save(flags);
mep->error = 0;
if (!write)
scsi_esp_cmd(esp, ESP_CMD_FLUSH);
esp_write8((esp_count >> 0) & 0xFF, ESP_TCLOW);
esp_write8((esp_count >> 8) & 0xFF, ESP_TCMED);
scsi_esp_cmd(esp, cmd);
do {
unsigned int count32 = esp_count >> 5;
unsigned int count2 = (esp_count & 0x1F) >> 1;
unsigned int start_addr = addr;
if (mac_esp_wait_for_dreq(esp))
break;
if (write) {
MAC_ESP_PDMA_LOOP("%1@,%0@+");
esp_count -= addr - start_addr;
} else {
unsigned int n;
MAC_ESP_PDMA_LOOP("%0@+,%1@");
if (mac_esp_wait_for_empty_fifo(esp))
break;
n = (esp_read8(ESP_TCMED) << 8) + esp_read8(ESP_TCLOW);
addr = start_addr + esp_count - n;
esp_count = n;
}
} while (esp_count);
local_irq_restore(flags);
}
/*
* Programmed IO routines follow.
*/
static inline int mac_esp_wait_for_fifo(struct esp *esp)
{
int i = 500000;
do {
if (esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES)
return 0;
udelay(2);
} while (--i);
printk(KERN_ERR PFX "FIFO is empty (sreg %02x)\n",
esp_read8(ESP_STATUS));
return 1;
}
static inline int mac_esp_wait_for_intr(struct esp *esp)
{
int i = 500000;
do {
esp->sreg = esp_read8(ESP_STATUS);
if (esp->sreg & ESP_STAT_INTR)
return 0;
udelay(2);
} while (--i);
printk(KERN_ERR PFX "IRQ timeout (sreg %02x)\n", esp->sreg);
return 1;
}
#define MAC_ESP_PIO_LOOP(operands, reg1) \
asm volatile ( \
"1: moveb " operands " \n" \
" subqw #1,%1 \n" \
" jbne 1b \n" \
: "+a" (addr), "+r" (reg1) \
: "a" (fifo))
#define MAC_ESP_PIO_FILL(operands, reg1) \
asm volatile ( \
" moveb " operands " \n" \
" moveb " operands " \n" \
" moveb " operands " \n" \
" moveb " operands " \n" \
" moveb " operands " \n" \
" moveb " operands " \n" \
" moveb " operands " \n" \
" moveb " operands " \n" \
" moveb " operands " \n" \
" moveb " operands " \n" \
" moveb " operands " \n" \
" moveb " operands " \n" \
" moveb " operands " \n" \
" moveb " operands " \n" \
" moveb " operands " \n" \
" moveb " operands " \n" \
" subqw #8,%1 \n" \
" subqw #8,%1 \n" \
: "+a" (addr), "+r" (reg1) \
: "a" (fifo))
#define MAC_ESP_FIFO_SIZE 16
static void mac_esp_send_pio_cmd(struct esp *esp, u32 addr, u32 esp_count,
u32 dma_count, int write, u8 cmd)
{
unsigned long flags;
struct mac_esp_priv *mep = MAC_ESP_GET_PRIV(esp);
u8 *fifo = esp->regs + ESP_FDATA * 16;
local_irq_save(flags);
cmd &= ~ESP_CMD_DMA;
mep->error = 0;
if (write) {
scsi_esp_cmd(esp, cmd);
if (!mac_esp_wait_for_intr(esp)) {
if (mac_esp_wait_for_fifo(esp))
esp_count = 0;
} else {
esp_count = 0;
}
} else {
scsi_esp_cmd(esp, ESP_CMD_FLUSH);
if (esp_count >= MAC_ESP_FIFO_SIZE)
MAC_ESP_PIO_FILL("%0@+,%2@", esp_count);
else
MAC_ESP_PIO_LOOP("%0@+,%2@", esp_count);
scsi_esp_cmd(esp, cmd);
}
while (esp_count) {
unsigned int n;
if (mac_esp_wait_for_intr(esp)) {
mep->error = 1;
break;
}
if (esp->sreg & ESP_STAT_SPAM) {
printk(KERN_ERR PFX "gross error\n");
mep->error = 1;
break;
}
n = esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES;
if (write) {
if (n > esp_count)
n = esp_count;
esp_count -= n;
MAC_ESP_PIO_LOOP("%2@,%0@+", n);
if ((esp->sreg & ESP_STAT_PMASK) == ESP_STATP)
break;
if (esp_count) {
esp->ireg = esp_read8(ESP_INTRPT);
if (esp->ireg & ESP_INTR_DC)
break;
scsi_esp_cmd(esp, ESP_CMD_TI);
}
} else {
esp->ireg = esp_read8(ESP_INTRPT);
if (esp->ireg & ESP_INTR_DC)
break;
n = MAC_ESP_FIFO_SIZE - n;
if (n > esp_count)
n = esp_count;
if (n == MAC_ESP_FIFO_SIZE) {
MAC_ESP_PIO_FILL("%0@+,%2@", esp_count);
} else {
esp_count -= n;
MAC_ESP_PIO_LOOP("%0@+,%2@", n);
}
scsi_esp_cmd(esp, ESP_CMD_TI);
}
}
local_irq_restore(flags);
}
static int mac_esp_irq_pending(struct esp *esp)
{
if (esp_read8(ESP_STATUS) & ESP_STAT_INTR)
return 1;
return 0;
}
static u32 mac_esp_dma_length_limit(struct esp *esp, u32 dma_addr, u32 dma_len)
{
return dma_len > 0xFFFF ? 0xFFFF : dma_len;
}
static struct esp_driver_ops mac_esp_ops = {
.esp_write8 = mac_esp_write8,
.esp_read8 = mac_esp_read8,
.map_single = mac_esp_map_single,
.map_sg = mac_esp_map_sg,
.unmap_single = mac_esp_unmap_single,
.unmap_sg = mac_esp_unmap_sg,
.irq_pending = mac_esp_irq_pending,
.dma_length_limit = mac_esp_dma_length_limit,
.reset_dma = mac_esp_reset_dma,
.dma_drain = mac_esp_dma_drain,
.dma_invalidate = mac_esp_dma_invalidate,
.send_dma_cmd = mac_esp_send_pdma_cmd,
.dma_error = mac_esp_dma_error,
};
static int __devinit esp_mac_probe(struct platform_device *dev)
{
struct scsi_host_template *tpnt = &scsi_esp_template;
struct Scsi_Host *host;
struct esp *esp;
int err;
int chips_present;
struct mac_esp_priv *mep;
if (!MACH_IS_MAC)
return -ENODEV;
switch (macintosh_config->scsi_type) {
case MAC_SCSI_QUADRA:
case MAC_SCSI_QUADRA3:
chips_present = 1;
break;
case MAC_SCSI_QUADRA2:
if ((macintosh_config->ident == MAC_MODEL_Q900) ||
(macintosh_config->ident == MAC_MODEL_Q950))
chips_present = 2;
else
chips_present = 1;
break;
default:
chips_present = 0;
}
if (dev->id + 1 > chips_present)
return -ENODEV;
host = scsi_host_alloc(tpnt, sizeof(struct esp));
err = -ENOMEM;
if (!host)
goto fail;
host->max_id = 8;
host->use_clustering = DISABLE_CLUSTERING;
esp = shost_priv(host);
esp->host = host;
esp->dev = dev;
esp->command_block = kzalloc(16, GFP_KERNEL);
if (!esp->command_block)
goto fail_unlink;
esp->command_block_dma = (dma_addr_t)esp->command_block;
esp->scsi_id = 7;
host->this_id = esp->scsi_id;
esp->scsi_id_mask = 1 << esp->scsi_id;
mep = kzalloc(sizeof(struct mac_esp_priv), GFP_KERNEL);
if (!mep)
goto fail_free_command_block;
mep->esp = esp;
platform_set_drvdata(dev, mep);
switch (macintosh_config->scsi_type) {
case MAC_SCSI_QUADRA:
esp->cfreq = 16500000;
esp->regs = (void __iomem *)MAC_ESP_REGS_QUADRA;
mep->pdma_io = esp->regs + MAC_ESP_PDMA_IO_OFFSET;
mep->pdma_regs = NULL;
break;
case MAC_SCSI_QUADRA2:
esp->cfreq = 25000000;
esp->regs = (void __iomem *)(MAC_ESP_REGS_QUADRA2 +
dev->id * MAC_ESP_REGS_SPACING);
mep->pdma_io = esp->regs + MAC_ESP_PDMA_IO_OFFSET;
mep->pdma_regs = (void __iomem *)(MAC_ESP_PDMA_REG +
dev->id * MAC_ESP_PDMA_REG_SPACING);
nubus_writel(0x1d1, mep->pdma_regs);
break;
case MAC_SCSI_QUADRA3:
/* These quadras have a real DMA controller (the PSC) but we
* don't know how to drive it so we must use PIO instead.
*/
esp->cfreq = 25000000;
esp->regs = (void __iomem *)MAC_ESP_REGS_QUADRA3;
mep->pdma_io = NULL;
mep->pdma_regs = NULL;
break;
}
esp->ops = &mac_esp_ops;
if (mep->pdma_io == NULL) {
printk(KERN_INFO PFX "using PIO for controller %d\n", dev->id);
esp_write8(0, ESP_TCLOW);
esp_write8(0, ESP_TCMED);
esp->flags = ESP_FLAG_DISABLE_SYNC;
mac_esp_ops.send_dma_cmd = mac_esp_send_pio_cmd;
} else {
printk(KERN_INFO PFX "using PDMA for controller %d\n", dev->id);
}
host->irq = IRQ_MAC_SCSI;
err = request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "Mac ESP",
esp);
if (err < 0)
goto fail_free_priv;
err = scsi_esp_register(esp, &dev->dev);
if (err)
goto fail_free_irq;
return 0;
fail_free_irq:
free_irq(host->irq, esp);
fail_free_priv:
kfree(mep);
fail_free_command_block:
kfree(esp->command_block);
fail_unlink:
scsi_host_put(host);
fail:
return err;
}
static int __devexit esp_mac_remove(struct platform_device *dev)
{
struct mac_esp_priv *mep = platform_get_drvdata(dev);
struct esp *esp = mep->esp;
unsigned int irq = esp->host->irq;
scsi_esp_unregister(esp);
free_irq(irq, esp);
kfree(mep);
kfree(esp->command_block);
scsi_host_put(esp->host);
return 0;
}
static struct platform_driver esp_mac_driver = {
.probe = esp_mac_probe,
.remove = __devexit_p(esp_mac_remove),
.driver = {
.name = DRV_MODULE_NAME,
},
};
static int __init mac_esp_init(void)
{
int err;
err = platform_driver_register(&esp_mac_driver);
if (err)
return err;
internal_esp = platform_device_alloc(DRV_MODULE_NAME, 0);
if (internal_esp && platform_device_add(internal_esp)) {
platform_device_put(internal_esp);
internal_esp = NULL;
}
external_esp = platform_device_alloc(DRV_MODULE_NAME, 1);
if (external_esp && platform_device_add(external_esp)) {
platform_device_put(external_esp);
external_esp = NULL;
}
if (internal_esp || external_esp) {
return 0;
} else {
platform_driver_unregister(&esp_mac_driver);
return -ENOMEM;
}
}
static void __exit mac_esp_exit(void)
{
platform_driver_unregister(&esp_mac_driver);
if (internal_esp) {
platform_device_unregister(internal_esp);
internal_esp = NULL;
}
if (external_esp) {
platform_device_unregister(external_esp);
external_esp = NULL;
}
}
MODULE_DESCRIPTION("Mac ESP SCSI driver");
MODULE_AUTHOR("Finn Thain <fthain@telegraphics.com.au>");
MODULE_LICENSE("GPLv2");
MODULE_VERSION(DRV_VERSION);
module_init(mac_esp_init);
module_exit(mac_esp_exit);

View File

@ -609,8 +609,8 @@ qla2x00_pci_info_show(struct device *dev, struct device_attribute *attr,
}
static ssize_t
qla2x00_state_show(struct device *dev, struct device_attribute *attr,
char *buf)
qla2x00_link_state_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
int len = 0;
@ -814,7 +814,7 @@ static DEVICE_ATTR(isp_id, S_IRUGO, qla2x00_isp_id_show, NULL);
static DEVICE_ATTR(model_name, S_IRUGO, qla2x00_model_name_show, NULL);
static DEVICE_ATTR(model_desc, S_IRUGO, qla2x00_model_desc_show, NULL);
static DEVICE_ATTR(pci_info, S_IRUGO, qla2x00_pci_info_show, NULL);
static DEVICE_ATTR(state, S_IRUGO, qla2x00_state_show, NULL);
static DEVICE_ATTR(link_state, S_IRUGO, qla2x00_link_state_show, NULL);
static DEVICE_ATTR(zio, S_IRUGO | S_IWUSR, qla2x00_zio_show, qla2x00_zio_store);
static DEVICE_ATTR(zio_timer, S_IRUGO | S_IWUSR, qla2x00_zio_timer_show,
qla2x00_zio_timer_store);
@ -838,7 +838,7 @@ struct device_attribute *qla2x00_host_attrs[] = {
&dev_attr_model_name,
&dev_attr_model_desc,
&dev_attr_pci_info,
&dev_attr_state,
&dev_attr_link_state,
&dev_attr_zio,
&dev_attr_zio_timer,
&dev_attr_beacon,

View File

@ -38,28 +38,38 @@ qla2xxx_copy_queues(scsi_qla_host_t *ha, void *ptr)
}
static int
qla24xx_dump_memory(scsi_qla_host_t *ha, uint32_t *code_ram,
uint32_t cram_size, uint32_t *ext_mem, void **nxt)
qla24xx_dump_ram(scsi_qla_host_t *ha, uint32_t addr, uint32_t *ram,
uint32_t ram_dwords, void **nxt)
{
int rval;
uint32_t cnt, stat, timer, risc_address, ext_mem_cnt;
uint16_t mb[4];
uint32_t cnt, stat, timer, dwords, idx;
uint16_t mb0;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
dma_addr_t dump_dma = ha->gid_list_dma;
uint32_t *dump = (uint32_t *)ha->gid_list;
rval = QLA_SUCCESS;
risc_address = ext_mem_cnt = 0;
memset(mb, 0, sizeof(mb));
mb0 = 0;
/* Code RAM. */
risc_address = 0x20000;
WRT_REG_WORD(&reg->mailbox0, MBC_READ_RAM_EXTENDED);
WRT_REG_WORD(&reg->mailbox0, MBC_DUMP_RISC_RAM_EXTENDED);
clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
for (cnt = 0; cnt < cram_size / 4 && rval == QLA_SUCCESS;
cnt++, risc_address++) {
WRT_REG_WORD(&reg->mailbox1, LSW(risc_address));
WRT_REG_WORD(&reg->mailbox8, MSW(risc_address));
RD_REG_WORD(&reg->mailbox8);
dwords = GID_LIST_SIZE / 4;
for (cnt = 0; cnt < ram_dwords && rval == QLA_SUCCESS;
cnt += dwords, addr += dwords) {
if (cnt + dwords > ram_dwords)
dwords = ram_dwords - cnt;
WRT_REG_WORD(&reg->mailbox1, LSW(addr));
WRT_REG_WORD(&reg->mailbox8, MSW(addr));
WRT_REG_WORD(&reg->mailbox2, MSW(dump_dma));
WRT_REG_WORD(&reg->mailbox3, LSW(dump_dma));
WRT_REG_WORD(&reg->mailbox6, MSW(MSD(dump_dma)));
WRT_REG_WORD(&reg->mailbox7, LSW(MSD(dump_dma)));
WRT_REG_WORD(&reg->mailbox4, MSW(dwords));
WRT_REG_WORD(&reg->mailbox5, LSW(dwords));
WRT_REG_DWORD(&reg->hccr, HCCRX_SET_HOST_INT);
for (timer = 6000000; timer; timer--) {
@ -73,9 +83,7 @@ qla24xx_dump_memory(scsi_qla_host_t *ha, uint32_t *code_ram,
set_bit(MBX_INTERRUPT,
&ha->mbx_cmd_flags);
mb[0] = RD_REG_WORD(&reg->mailbox0);
mb[2] = RD_REG_WORD(&reg->mailbox2);
mb[3] = RD_REG_WORD(&reg->mailbox3);
mb0 = RD_REG_WORD(&reg->mailbox0);
WRT_REG_DWORD(&reg->hccr,
HCCRX_CLR_RISC_INT);
@ -91,67 +99,34 @@ qla24xx_dump_memory(scsi_qla_host_t *ha, uint32_t *code_ram,
}
if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
rval = mb[0] & MBS_MASK;
code_ram[cnt] = htonl((mb[3] << 16) | mb[2]);
rval = mb0 & MBS_MASK;
for (idx = 0; idx < dwords; idx++)
ram[cnt + idx] = swab32(dump[idx]);
} else {
rval = QLA_FUNCTION_FAILED;
}
}
if (rval == QLA_SUCCESS) {
/* External Memory. */
risc_address = 0x100000;
ext_mem_cnt = ha->fw_memory_size - 0x100000 + 1;
WRT_REG_WORD(&reg->mailbox0, MBC_READ_RAM_EXTENDED);
clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
}
for (cnt = 0; cnt < ext_mem_cnt && rval == QLA_SUCCESS;
cnt++, risc_address++) {
WRT_REG_WORD(&reg->mailbox1, LSW(risc_address));
WRT_REG_WORD(&reg->mailbox8, MSW(risc_address));
RD_REG_WORD(&reg->mailbox8);
WRT_REG_DWORD(&reg->hccr, HCCRX_SET_HOST_INT);
for (timer = 6000000; timer; timer--) {
/* Check for pending interrupts. */
stat = RD_REG_DWORD(&reg->host_status);
if (stat & HSRX_RISC_INT) {
stat &= 0xff;
if (stat == 0x1 || stat == 0x2 ||
stat == 0x10 || stat == 0x11) {
set_bit(MBX_INTERRUPT,
&ha->mbx_cmd_flags);
mb[0] = RD_REG_WORD(&reg->mailbox0);
mb[2] = RD_REG_WORD(&reg->mailbox2);
mb[3] = RD_REG_WORD(&reg->mailbox3);
WRT_REG_DWORD(&reg->hccr,
HCCRX_CLR_RISC_INT);
RD_REG_DWORD(&reg->hccr);
break;
}
/* Clear this intr; it wasn't a mailbox intr */
WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
RD_REG_DWORD(&reg->hccr);
}
udelay(5);
}
if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
rval = mb[0] & MBS_MASK;
ext_mem[cnt] = htonl((mb[3] << 16) | mb[2]);
} else {
rval = QLA_FUNCTION_FAILED;
}
}
*nxt = rval == QLA_SUCCESS ? &ext_mem[cnt]: NULL;
*nxt = rval == QLA_SUCCESS ? &ram[cnt]: NULL;
return rval;
}
static int
qla24xx_dump_memory(scsi_qla_host_t *ha, uint32_t *code_ram,
uint32_t cram_size, void **nxt)
{
int rval;
/* Code RAM. */
rval = qla24xx_dump_ram(ha, 0x20000, code_ram, cram_size / 4, nxt);
if (rval != QLA_SUCCESS)
return rval;
/* External Memory. */
return qla24xx_dump_ram(ha, 0x100000, *nxt,
ha->fw_memory_size - 0x100000 + 1, nxt);
}
static uint32_t *
qla24xx_read_window(struct device_reg_24xx __iomem *reg, uint32_t iobase,
uint32_t count, uint32_t *buf)
@ -239,6 +214,90 @@ qla24xx_soft_reset(scsi_qla_host_t *ha)
return rval;
}
static int
qla2xxx_dump_ram(scsi_qla_host_t *ha, uint32_t addr, uint16_t *ram,
uint16_t ram_words, void **nxt)
{
int rval;
uint32_t cnt, stat, timer, words, idx;
uint16_t mb0;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
dma_addr_t dump_dma = ha->gid_list_dma;
uint16_t *dump = (uint16_t *)ha->gid_list;
rval = QLA_SUCCESS;
mb0 = 0;
WRT_MAILBOX_REG(ha, reg, 0, MBC_DUMP_RISC_RAM_EXTENDED);
clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
words = GID_LIST_SIZE / 2;
for (cnt = 0; cnt < ram_words && rval == QLA_SUCCESS;
cnt += words, addr += words) {
if (cnt + words > ram_words)
words = ram_words - cnt;
WRT_MAILBOX_REG(ha, reg, 1, LSW(addr));
WRT_MAILBOX_REG(ha, reg, 8, MSW(addr));
WRT_MAILBOX_REG(ha, reg, 2, MSW(dump_dma));
WRT_MAILBOX_REG(ha, reg, 3, LSW(dump_dma));
WRT_MAILBOX_REG(ha, reg, 6, MSW(MSD(dump_dma)));
WRT_MAILBOX_REG(ha, reg, 7, LSW(MSD(dump_dma)));
WRT_MAILBOX_REG(ha, reg, 4, words);
WRT_REG_WORD(&reg->hccr, HCCR_SET_HOST_INT);
for (timer = 6000000; timer; timer--) {
/* Check for pending interrupts. */
stat = RD_REG_DWORD(&reg->u.isp2300.host_status);
if (stat & HSR_RISC_INT) {
stat &= 0xff;
if (stat == 0x1 || stat == 0x2) {
set_bit(MBX_INTERRUPT,
&ha->mbx_cmd_flags);
mb0 = RD_MAILBOX_REG(ha, reg, 0);
/* Release mailbox registers. */
WRT_REG_WORD(&reg->semaphore, 0);
WRT_REG_WORD(&reg->hccr,
HCCR_CLR_RISC_INT);
RD_REG_WORD(&reg->hccr);
break;
} else if (stat == 0x10 || stat == 0x11) {
set_bit(MBX_INTERRUPT,
&ha->mbx_cmd_flags);
mb0 = RD_MAILBOX_REG(ha, reg, 0);
WRT_REG_WORD(&reg->hccr,
HCCR_CLR_RISC_INT);
RD_REG_WORD(&reg->hccr);
break;
}
/* clear this intr; it wasn't a mailbox intr */
WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
RD_REG_WORD(&reg->hccr);
}
udelay(5);
}
if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
rval = mb0 & MBS_MASK;
for (idx = 0; idx < words; idx++)
ram[cnt + idx] = swab16(dump[idx]);
} else {
rval = QLA_FUNCTION_FAILED;
}
}
*nxt = rval == QLA_SUCCESS ? &ram[cnt]: NULL;
return rval;
}
static inline void
qla2xxx_read_window(struct device_reg_2xxx __iomem *reg, uint32_t count,
uint16_t *buf)
@ -258,19 +317,14 @@ void
qla2300_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
{
int rval;
uint32_t cnt, timer;
uint32_t risc_address;
uint16_t mb0, mb2;
uint32_t cnt;
uint32_t stat;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
uint16_t __iomem *dmp_reg;
unsigned long flags;
struct qla2300_fw_dump *fw;
uint32_t data_ram_cnt;
void *nxt;
risc_address = data_ram_cnt = 0;
mb0 = mb2 = 0;
flags = 0;
if (!hardware_locked)
@ -388,185 +442,23 @@ qla2300_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
}
}
if (rval == QLA_SUCCESS) {
/* Get RISC SRAM. */
risc_address = 0x800;
WRT_MAILBOX_REG(ha, reg, 0, MBC_READ_RAM_WORD);
clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
}
for (cnt = 0; cnt < sizeof(fw->risc_ram) / 2 && rval == QLA_SUCCESS;
cnt++, risc_address++) {
WRT_MAILBOX_REG(ha, reg, 1, (uint16_t)risc_address);
WRT_REG_WORD(&reg->hccr, HCCR_SET_HOST_INT);
/* Get RISC SRAM. */
if (rval == QLA_SUCCESS)
rval = qla2xxx_dump_ram(ha, 0x800, fw->risc_ram,
sizeof(fw->risc_ram) / 2, &nxt);
for (timer = 6000000; timer; timer--) {
/* Check for pending interrupts. */
stat = RD_REG_DWORD(&reg->u.isp2300.host_status);
if (stat & HSR_RISC_INT) {
stat &= 0xff;
/* Get stack SRAM. */
if (rval == QLA_SUCCESS)
rval = qla2xxx_dump_ram(ha, 0x10000, fw->stack_ram,
sizeof(fw->stack_ram) / 2, &nxt);
if (stat == 0x1 || stat == 0x2) {
set_bit(MBX_INTERRUPT,
&ha->mbx_cmd_flags);
mb0 = RD_MAILBOX_REG(ha, reg, 0);
mb2 = RD_MAILBOX_REG(ha, reg, 2);
/* Release mailbox registers. */
WRT_REG_WORD(&reg->semaphore, 0);
WRT_REG_WORD(&reg->hccr,
HCCR_CLR_RISC_INT);
RD_REG_WORD(&reg->hccr);
break;
} else if (stat == 0x10 || stat == 0x11) {
set_bit(MBX_INTERRUPT,
&ha->mbx_cmd_flags);
mb0 = RD_MAILBOX_REG(ha, reg, 0);
mb2 = RD_MAILBOX_REG(ha, reg, 2);
WRT_REG_WORD(&reg->hccr,
HCCR_CLR_RISC_INT);
RD_REG_WORD(&reg->hccr);
break;
}
/* clear this intr; it wasn't a mailbox intr */
WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
RD_REG_WORD(&reg->hccr);
}
udelay(5);
}
if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
rval = mb0 & MBS_MASK;
fw->risc_ram[cnt] = htons(mb2);
} else {
rval = QLA_FUNCTION_FAILED;
}
}
if (rval == QLA_SUCCESS) {
/* Get stack SRAM. */
risc_address = 0x10000;
WRT_MAILBOX_REG(ha, reg, 0, MBC_READ_RAM_EXTENDED);
clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
}
for (cnt = 0; cnt < sizeof(fw->stack_ram) / 2 && rval == QLA_SUCCESS;
cnt++, risc_address++) {
WRT_MAILBOX_REG(ha, reg, 1, LSW(risc_address));
WRT_MAILBOX_REG(ha, reg, 8, MSW(risc_address));
WRT_REG_WORD(&reg->hccr, HCCR_SET_HOST_INT);
for (timer = 6000000; timer; timer--) {
/* Check for pending interrupts. */
stat = RD_REG_DWORD(&reg->u.isp2300.host_status);
if (stat & HSR_RISC_INT) {
stat &= 0xff;
if (stat == 0x1 || stat == 0x2) {
set_bit(MBX_INTERRUPT,
&ha->mbx_cmd_flags);
mb0 = RD_MAILBOX_REG(ha, reg, 0);
mb2 = RD_MAILBOX_REG(ha, reg, 2);
/* Release mailbox registers. */
WRT_REG_WORD(&reg->semaphore, 0);
WRT_REG_WORD(&reg->hccr,
HCCR_CLR_RISC_INT);
RD_REG_WORD(&reg->hccr);
break;
} else if (stat == 0x10 || stat == 0x11) {
set_bit(MBX_INTERRUPT,
&ha->mbx_cmd_flags);
mb0 = RD_MAILBOX_REG(ha, reg, 0);
mb2 = RD_MAILBOX_REG(ha, reg, 2);
WRT_REG_WORD(&reg->hccr,
HCCR_CLR_RISC_INT);
RD_REG_WORD(&reg->hccr);
break;
}
/* clear this intr; it wasn't a mailbox intr */
WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
RD_REG_WORD(&reg->hccr);
}
udelay(5);
}
if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
rval = mb0 & MBS_MASK;
fw->stack_ram[cnt] = htons(mb2);
} else {
rval = QLA_FUNCTION_FAILED;
}
}
if (rval == QLA_SUCCESS) {
/* Get data SRAM. */
risc_address = 0x11000;
data_ram_cnt = ha->fw_memory_size - risc_address + 1;
WRT_MAILBOX_REG(ha, reg, 0, MBC_READ_RAM_EXTENDED);
clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
}
for (cnt = 0; cnt < data_ram_cnt && rval == QLA_SUCCESS;
cnt++, risc_address++) {
WRT_MAILBOX_REG(ha, reg, 1, LSW(risc_address));
WRT_MAILBOX_REG(ha, reg, 8, MSW(risc_address));
WRT_REG_WORD(&reg->hccr, HCCR_SET_HOST_INT);
for (timer = 6000000; timer; timer--) {
/* Check for pending interrupts. */
stat = RD_REG_DWORD(&reg->u.isp2300.host_status);
if (stat & HSR_RISC_INT) {
stat &= 0xff;
if (stat == 0x1 || stat == 0x2) {
set_bit(MBX_INTERRUPT,
&ha->mbx_cmd_flags);
mb0 = RD_MAILBOX_REG(ha, reg, 0);
mb2 = RD_MAILBOX_REG(ha, reg, 2);
/* Release mailbox registers. */
WRT_REG_WORD(&reg->semaphore, 0);
WRT_REG_WORD(&reg->hccr,
HCCR_CLR_RISC_INT);
RD_REG_WORD(&reg->hccr);
break;
} else if (stat == 0x10 || stat == 0x11) {
set_bit(MBX_INTERRUPT,
&ha->mbx_cmd_flags);
mb0 = RD_MAILBOX_REG(ha, reg, 0);
mb2 = RD_MAILBOX_REG(ha, reg, 2);
WRT_REG_WORD(&reg->hccr,
HCCR_CLR_RISC_INT);
RD_REG_WORD(&reg->hccr);
break;
}
/* clear this intr; it wasn't a mailbox intr */
WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
RD_REG_WORD(&reg->hccr);
}
udelay(5);
}
if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
rval = mb0 & MBS_MASK;
fw->data_ram[cnt] = htons(mb2);
} else {
rval = QLA_FUNCTION_FAILED;
}
}
/* Get data SRAM. */
if (rval == QLA_SUCCESS)
rval = qla2xxx_dump_ram(ha, 0x11000, fw->data_ram,
ha->fw_memory_size - 0x11000 + 1, &nxt);
if (rval == QLA_SUCCESS)
qla2xxx_copy_queues(ha, &fw->data_ram[cnt]);
qla2xxx_copy_queues(ha, nxt);
if (rval != QLA_SUCCESS) {
qla_printk(KERN_WARNING, ha,
@ -1010,7 +902,7 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
goto qla24xx_fw_dump_failed_0;
rval = qla24xx_dump_memory(ha, fw->code_ram, sizeof(fw->code_ram),
fw->ext_mem, &nxt);
&nxt);
if (rval != QLA_SUCCESS)
goto qla24xx_fw_dump_failed_0;
@ -1318,7 +1210,7 @@ qla25xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
goto qla25xx_fw_dump_failed_0;
rval = qla24xx_dump_memory(ha, fw->code_ram, sizeof(fw->code_ram),
fw->ext_mem, &nxt);
&nxt);
if (rval != QLA_SUCCESS)
goto qla25xx_fw_dump_failed_0;

View File

@ -1036,22 +1036,6 @@ struct mid_db_entry_24xx {
uint8_t reserved_1;
};
/*
* Virtual Fabric ID type definition.
*/
typedef struct vf_id {
uint16_t id : 12;
uint16_t priority : 4;
} vf_id_t;
/*
* Virtual Fabric HopCt type definition.
*/
typedef struct vf_hopct {
uint16_t reserved : 8;
uint16_t hopct : 8;
} vf_hopct_t;
/*
* Virtual Port Control IOCB
*/
@ -1082,10 +1066,10 @@ struct vp_ctrl_entry_24xx {
uint8_t vp_idx_map[16];
uint16_t flags;
struct vf_id id;
uint16_t id;
uint16_t reserved_4;
struct vf_hopct hopct;
uint8_t reserved_5[8];
uint16_t hopct;
uint8_t reserved_5[24];
};
/*
@ -1132,9 +1116,9 @@ struct vp_config_entry_24xx {
uint16_t reserved_vp2;
uint8_t port_name_idx2[WWN_SIZE];
uint8_t node_name_idx2[WWN_SIZE];
struct vf_id id;
uint16_t id;
uint16_t reserved_4;
struct vf_hopct hopct;
uint16_t hopct;
uint8_t reserved_5;
};

View File

@ -151,10 +151,6 @@ qla2x00_verify_checksum(scsi_qla_host_t *, uint32_t);
extern int
qla2x00_issue_iocb(scsi_qla_host_t *, void *, dma_addr_t, size_t);
extern int
qla2x00_issue_iocb_timeout(scsi_qla_host_t *, void *, dma_addr_t, size_t,
uint32_t);
extern int
qla2x00_abort_command(scsi_qla_host_t *, srb_t *);

View File

@ -1583,8 +1583,8 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha)
eiter->type = __constant_cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE);
eiter->len = __constant_cpu_to_be16(4 + 4);
max_frame_size = IS_FWI2_CAPABLE(ha) ?
(uint32_t) icb24->frame_payload_size:
(uint32_t) ha->init_cb->frame_payload_size;
le16_to_cpu(icb24->frame_payload_size):
le16_to_cpu(ha->init_cb->frame_payload_size);
eiter->a.max_frame_size = cpu_to_be32(max_frame_size);
size += 4 + 4;

View File

@ -3645,7 +3645,7 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
if (le16_to_cpu(nv->login_timeout) < 4)
nv->login_timeout = __constant_cpu_to_le16(4);
ha->login_timeout = le16_to_cpu(nv->login_timeout);
icb->login_timeout = cpu_to_le16(nv->login_timeout);
icb->login_timeout = nv->login_timeout;
/* Set minimum RATOV to 100 tenths of a second. */
ha->r_a_tov = 100;

View File

@ -409,6 +409,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
}
set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags);
set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags);
ha->flags.management_server_logged_in = 0;
qla2x00_post_aen_work(ha, FCH_EVT_LIP, mb[1]);
@ -454,8 +455,6 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
ha->flags.management_server_logged_in = 0;
ha->link_data_rate = PORT_SPEED_UNKNOWN;
if (ql2xfdmienable)
set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags);
qla2x00_post_aen_work(ha, FCH_EVT_LINKDOWN, 0);
break;
@ -511,6 +510,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
set_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
}
set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags);
set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags);
ha->flags.gpsc_supported = 1;
ha->flags.management_server_logged_in = 0;

View File

@ -681,7 +681,7 @@ qla2x00_verify_checksum(scsi_qla_host_t *ha, uint32_t risc_addr)
* Context:
* Kernel context.
*/
int
static int
qla2x00_issue_iocb_timeout(scsi_qla_host_t *ha, void *buffer,
dma_addr_t phys_addr, size_t size, uint32_t tov)
{
@ -784,7 +784,6 @@ qla2x00_abort_command(scsi_qla_host_t *ha, srb_t *sp)
DEBUG2_3_11(printk("qla2x00_abort_command(%ld): failed=%x.\n",
ha->host_no, rval));
} else {
sp->flags |= SRB_ABORT_PENDING;
DEBUG11(printk("qla2x00_abort_command(%ld): done.\n",
ha->host_no));
}
@ -1469,7 +1468,7 @@ qla24xx_login_fabric(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain,
lg->port_id[0] = al_pa;
lg->port_id[1] = area;
lg->port_id[2] = domain;
lg->vp_index = cpu_to_le16(ha->vp_idx);
lg->vp_index = ha->vp_idx;
rval = qla2x00_issue_iocb(ha, lg, lg_dma, 0);
if (rval != QLA_SUCCESS) {
DEBUG2_3_11(printk("%s(%ld): failed to issue Login IOCB "
@ -1724,7 +1723,7 @@ qla24xx_fabric_logout(scsi_qla_host_t *ha, uint16_t loop_id, uint8_t domain,
lg->port_id[0] = al_pa;
lg->port_id[1] = area;
lg->port_id[2] = domain;
lg->vp_index = cpu_to_le16(ha->vp_idx);
lg->vp_index = ha->vp_idx;
rval = qla2x00_issue_iocb(ha, lg, lg_dma, 0);
if (rval != QLA_SUCCESS) {
DEBUG2_3_11(printk("%s(%ld): failed to issue Logout IOCB "
@ -2210,7 +2209,6 @@ qla24xx_abort_command(scsi_qla_host_t *ha, srb_t *sp)
rval = QLA_FUNCTION_FAILED;
} else {
DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
sp->flags |= SRB_ABORT_PENDING;
}
dma_pool_free(ha->s_dma_pool, abt, abt_dma);
@ -2644,12 +2642,11 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *ha,
struct vp_rpt_id_entry_24xx *rptid_entry)
{
uint8_t vp_idx;
uint16_t stat = le16_to_cpu(rptid_entry->vp_idx);
scsi_qla_host_t *vha;
if (rptid_entry->entry_status != 0)
return;
if (rptid_entry->entry_status != __constant_cpu_to_le16(CS_COMPLETE))
return;
if (rptid_entry->format == 0) {
DEBUG15(printk("%s:format 0 : scsi(%ld) number of VPs setup %d,"
@ -2659,17 +2656,17 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *ha,
rptid_entry->port_id[2], rptid_entry->port_id[1],
rptid_entry->port_id[0]));
} else if (rptid_entry->format == 1) {
vp_idx = LSB(rptid_entry->vp_idx);
vp_idx = LSB(stat);
DEBUG15(printk("%s:format 1: scsi(%ld): VP[%d] enabled "
"- status %d - "
"with port id %02x%02x%02x\n",__func__,ha->host_no,
vp_idx, MSB(rptid_entry->vp_idx),
vp_idx, MSB(stat),
rptid_entry->port_id[2], rptid_entry->port_id[1],
rptid_entry->port_id[0]));
if (vp_idx == 0)
return;
if (MSB(rptid_entry->vp_idx) == 1)
if (MSB(stat) == 1)
return;
list_for_each_entry(vha, &ha->vp_list, vp_list)
@ -2982,8 +2979,8 @@ qla84xx_verify_chip(struct scsi_qla_host *ha, uint16_t *status)
/* We update the firmware with only one data sequence. */
options |= VCO_END_OF_DATA;
retry = 0;
do {
retry = 0;
memset(mn, 0, sizeof(*mn));
mn->p.req.entry_type = VERIFY_CHIP_IOCB_TYPE;
mn->p.req.entry_count = 1;

View File

@ -67,7 +67,7 @@ static void qla2x00_free_device(scsi_qla_host_t *);
static void qla2x00_config_dma_addressing(scsi_qla_host_t *ha);
int ql2xfdmienable;
int ql2xfdmienable=1;
module_param(ql2xfdmienable, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xfdmienable,
"Enables FDMI registratons "
@ -2135,7 +2135,7 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
kfree(ha->nvram);
}
struct qla_work_evt *
static struct qla_work_evt *
qla2x00_alloc_work(struct scsi_qla_host *ha, enum qla_work_type type,
int locked)
{
@ -2152,7 +2152,7 @@ qla2x00_alloc_work(struct scsi_qla_host *ha, enum qla_work_type type,
return e;
}
int
static int
qla2x00_post_work(struct scsi_qla_host *ha, struct qla_work_evt *e, int locked)
{
unsigned long flags;
@ -2373,7 +2373,7 @@ qla2x00_do_dpc(void *data)
} else {
fcport->login_retry = 0;
}
if (fcport->login_retry == 0)
if (fcport->login_retry == 0 && status != QLA_SUCCESS)
fcport->loop_id = FC_NO_LOOP_ID;
}
if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags))
@ -2599,6 +2599,10 @@ qla2x00_timer(scsi_qla_host_t *ha)
start_dpc++;
}
/* Process any deferred work. */
if (!list_empty(&ha->work_list))
start_dpc++;
/* Schedule the DPC routine if needed */
if ((test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) ||
test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) ||

View File

@ -7,7 +7,7 @@
/*
* Driver version
*/
#define QLA2XXX_VERSION "8.02.01-k1"
#define QLA2XXX_VERSION "8.02.01-k2"
#define QLA_DRIVER_MAJOR_VER 8
#define QLA_DRIVER_MINOR_VER 2

View File

@ -121,6 +121,7 @@ extern struct scsi_transport_template blank_transport_template;
extern void __scsi_remove_device(struct scsi_device *);
extern struct bus_type scsi_bus_type;
extern struct attribute_group *scsi_sysfs_shost_attr_groups[];
/* scsi_netlink.c */
#ifdef CONFIG_SCSI_NETLINK

View File

@ -190,10 +190,14 @@ void scsi_proc_host_rm(struct Scsi_Host *shost)
*/
static int proc_print_scsidevice(struct device *dev, void *data)
{
struct scsi_device *sdev = to_scsi_device(dev);
struct scsi_device *sdev;
struct seq_file *s = data;
int i;
if (!scsi_is_sdev_device(dev))
goto out;
sdev = to_scsi_device(dev);
seq_printf(s,
"Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n Vendor: ",
sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
@ -230,6 +234,7 @@ static int proc_print_scsidevice(struct device *dev, void *data)
else
seq_printf(s, "\n");
out:
return 0;
}

View File

@ -322,6 +322,21 @@ out:
return NULL;
}
static void scsi_target_destroy(struct scsi_target *starget)
{
struct device *dev = &starget->dev;
struct Scsi_Host *shost = dev_to_shost(dev->parent);
unsigned long flags;
transport_destroy_device(dev);
spin_lock_irqsave(shost->host_lock, flags);
if (shost->hostt->target_destroy)
shost->hostt->target_destroy(starget);
list_del_init(&starget->siblings);
spin_unlock_irqrestore(shost->host_lock, flags);
put_device(dev);
}
static void scsi_target_dev_release(struct device *dev)
{
struct device *parent = dev->parent;
@ -331,9 +346,14 @@ static void scsi_target_dev_release(struct device *dev)
put_device(parent);
}
struct device_type scsi_target_type = {
.name = "scsi_target",
.release = scsi_target_dev_release,
};
int scsi_is_target_device(const struct device *dev)
{
return dev->release == scsi_target_dev_release;
return dev->type == &scsi_target_type;
}
EXPORT_SYMBOL(scsi_is_target_device);
@ -391,14 +411,17 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
device_initialize(dev);
starget->reap_ref = 1;
dev->parent = get_device(parent);
dev->release = scsi_target_dev_release;
sprintf(dev->bus_id, "target%d:%d:%d",
shost->host_no, channel, id);
#ifndef CONFIG_SYSFS_DEPRECATED
dev->bus = &scsi_bus_type;
#endif
dev->type = &scsi_target_type;
starget->id = id;
starget->channel = channel;
INIT_LIST_HEAD(&starget->siblings);
INIT_LIST_HEAD(&starget->devices);
starget->state = STARGET_RUNNING;
starget->state = STARGET_CREATED;
starget->scsi_level = SCSI_2;
retry:
spin_lock_irqsave(shost->host_lock, flags);
@ -411,18 +434,6 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
spin_unlock_irqrestore(shost->host_lock, flags);
/* allocate and add */
transport_setup_device(dev);
error = device_add(dev);
if (error) {
dev_err(dev, "target device_add failed, error %d\n", error);
spin_lock_irqsave(shost->host_lock, flags);
list_del_init(&starget->siblings);
spin_unlock_irqrestore(shost->host_lock, flags);
transport_destroy_device(dev);
put_device(parent);
kfree(starget);
return NULL;
}
transport_add_device(dev);
if (shost->hostt->target_alloc) {
error = shost->hostt->target_alloc(starget);
@ -430,9 +441,7 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
dev_printk(KERN_ERR, dev, "target allocation failed, error %d\n", error);
/* don't want scsi_target_reap to do the final
* put because it will be under the host lock */
get_device(dev);
scsi_target_reap(starget);
put_device(dev);
scsi_target_destroy(starget);
return NULL;
}
}
@ -459,18 +468,10 @@ static void scsi_target_reap_usercontext(struct work_struct *work)
{
struct scsi_target *starget =
container_of(work, struct scsi_target, ew.work);
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
unsigned long flags;
transport_remove_device(&starget->dev);
device_del(&starget->dev);
transport_destroy_device(&starget->dev);
spin_lock_irqsave(shost->host_lock, flags);
if (shost->hostt->target_destroy)
shost->hostt->target_destroy(starget);
list_del_init(&starget->siblings);
spin_unlock_irqrestore(shost->host_lock, flags);
put_device(&starget->dev);
scsi_target_destroy(starget);
}
/**
@ -485,21 +486,25 @@ void scsi_target_reap(struct scsi_target *starget)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
unsigned long flags;
enum scsi_target_state state;
int empty;
spin_lock_irqsave(shost->host_lock, flags);
if (--starget->reap_ref == 0 && list_empty(&starget->devices)) {
BUG_ON(starget->state == STARGET_DEL);
starget->state = STARGET_DEL;
spin_unlock_irqrestore(shost->host_lock, flags);
execute_in_process_context(scsi_target_reap_usercontext,
&starget->ew);
return;
}
state = starget->state;
empty = --starget->reap_ref == 0 &&
list_empty(&starget->devices) ? 1 : 0;
spin_unlock_irqrestore(shost->host_lock, flags);
return;
if (!empty)
return;
BUG_ON(state == STARGET_DEL);
starget->state = STARGET_DEL;
if (state == STARGET_CREATED)
scsi_target_destroy(starget);
else
execute_in_process_context(scsi_target_reap_usercontext,
&starget->ew);
}
/**
@ -1048,8 +1053,9 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget,
scsi_inq_str(vend, result, 8, 16),
scsi_inq_str(mod, result, 16, 32));
});
}
res = SCSI_SCAN_TARGET_PRESENT;
goto out_free_result;
}
@ -1489,7 +1495,6 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,
if (scsi_host_scan_allowed(shost))
scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata);
mutex_unlock(&shost->scan_mutex);
transport_configure_device(&starget->dev);
scsi_target_reap(starget);
put_device(&starget->dev);
@ -1570,7 +1575,6 @@ static void __scsi_scan_target(struct device *parent, unsigned int channel,
out_reap:
/* now determine if the target has any children at all
* and if not, nuke it */
transport_configure_device(&starget->dev);
scsi_target_reap(starget);
put_device(&starget->dev);

View File

@ -21,6 +21,8 @@
#include "scsi_priv.h"
#include "scsi_logging.h"
static struct device_type scsi_dev_type;
static const struct {
enum scsi_device_state value;
char *name;
@ -249,18 +251,27 @@ shost_rd_attr(sg_tablesize, "%hu\n");
shost_rd_attr(unchecked_isa_dma, "%d\n");
shost_rd_attr2(proc_name, hostt->proc_name, "%s\n");
static struct device_attribute *scsi_sysfs_shost_attrs[] = {
&dev_attr_unique_id,
&dev_attr_host_busy,
&dev_attr_cmd_per_lun,
&dev_attr_can_queue,
&dev_attr_sg_tablesize,
&dev_attr_unchecked_isa_dma,
&dev_attr_proc_name,
&dev_attr_scan,
&dev_attr_hstate,
&dev_attr_supported_mode,
&dev_attr_active_mode,
static struct attribute *scsi_sysfs_shost_attrs[] = {
&dev_attr_unique_id.attr,
&dev_attr_host_busy.attr,
&dev_attr_cmd_per_lun.attr,
&dev_attr_can_queue.attr,
&dev_attr_sg_tablesize.attr,
&dev_attr_unchecked_isa_dma.attr,
&dev_attr_proc_name.attr,
&dev_attr_scan.attr,
&dev_attr_hstate.attr,
&dev_attr_supported_mode.attr,
&dev_attr_active_mode.attr,
NULL
};
struct attribute_group scsi_shost_attr_group = {
.attrs = scsi_sysfs_shost_attrs,
};
struct attribute_group *scsi_sysfs_shost_attr_groups[] = {
&scsi_shost_attr_group,
NULL
};
@ -335,7 +346,12 @@ static struct class sdev_class = {
/* all probing is done in the individual ->probe routines */
static int scsi_bus_match(struct device *dev, struct device_driver *gendrv)
{
struct scsi_device *sdp = to_scsi_device(dev);
struct scsi_device *sdp;
if (dev->type != &scsi_dev_type)
return 0;
sdp = to_scsi_device(dev);
if (sdp->no_uld_attach)
return 0;
return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0;
@ -351,10 +367,16 @@ static int scsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
static int scsi_bus_suspend(struct device * dev, pm_message_t state)
{
struct device_driver *drv = dev->driver;
struct scsi_device *sdev = to_scsi_device(dev);
struct device_driver *drv;
struct scsi_device *sdev;
int err;
if (dev->type != &scsi_dev_type)
return 0;
drv = dev->driver;
sdev = to_scsi_device(dev);
err = scsi_device_quiesce(sdev);
if (err)
return err;
@ -370,10 +392,16 @@ static int scsi_bus_suspend(struct device * dev, pm_message_t state)
static int scsi_bus_resume(struct device * dev)
{
struct device_driver *drv = dev->driver;
struct scsi_device *sdev = to_scsi_device(dev);
struct device_driver *drv;
struct scsi_device *sdev;
int err = 0;
if (dev->type != &scsi_dev_type)
return 0;
drv = dev->driver;
sdev = to_scsi_device(dev);
if (drv && drv->resume)
err = drv->resume(dev);
@ -781,6 +809,27 @@ sdev_store_queue_type_rw(struct device *dev, struct device_attribute *attr,
return count;
}
static int scsi_target_add(struct scsi_target *starget)
{
int error;
if (starget->state != STARGET_CREATED)
return 0;
error = device_add(&starget->dev);
if (error) {
dev_err(&starget->dev, "target device_add failed, error %d\n", error);
get_device(&starget->dev);
scsi_target_reap(starget);
put_device(&starget->dev);
return error;
}
transport_add_device(&starget->dev);
starget->state = STARGET_RUNNING;
return 0;
}
static struct device_attribute sdev_attr_queue_type_rw =
__ATTR(queue_type, S_IRUGO | S_IWUSR, show_queue_type_field,
sdev_store_queue_type_rw);
@ -796,10 +845,16 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
{
int error, i;
struct request_queue *rq = sdev->request_queue;
struct scsi_target *starget = sdev->sdev_target;
if ((error = scsi_device_set_state(sdev, SDEV_RUNNING)) != 0)
return error;
error = scsi_target_add(starget);
if (error)
return error;
transport_configure_device(&starget->dev);
error = device_add(&sdev->sdev_gendev);
if (error) {
put_device(sdev->sdev_gendev.parent);
@ -834,7 +889,7 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
goto out;
}
error = bsg_register_queue(rq, &sdev->sdev_gendev, NULL);
error = bsg_register_queue(rq, &sdev->sdev_gendev, NULL, NULL);
if (error)
sdev_printk(KERN_INFO, sdev,
@ -971,44 +1026,6 @@ int scsi_register_interface(struct class_interface *intf)
}
EXPORT_SYMBOL(scsi_register_interface);
static struct device_attribute *class_attr_overridden(
struct device_attribute **attrs,
struct device_attribute *attr)
{
int i;
if (!attrs)
return NULL;
for (i = 0; attrs[i]; i++)
if (!strcmp(attrs[i]->attr.name, attr->attr.name))
return attrs[i];
return NULL;
}
static int class_attr_add(struct device *classdev,
struct device_attribute *attr)
{
struct device_attribute *base_attr;
/*
* Spare the caller from having to copy things it's not interested in.
*/
base_attr = class_attr_overridden(scsi_sysfs_shost_attrs, attr);
if (base_attr) {
/* extend permissions */
attr->attr.mode |= base_attr->attr.mode;
/* override null show/store with default */
if (!attr->show)
attr->show = base_attr->show;
if (!attr->store)
attr->store = base_attr->store;
}
return device_create_file(classdev, attr);
}
/**
* scsi_sysfs_add_host - add scsi host to subsystem
* @shost: scsi host struct to add to subsystem
@ -1018,20 +1035,11 @@ int scsi_sysfs_add_host(struct Scsi_Host *shost)
{
int error, i;
/* add host specific attributes */
if (shost->hostt->shost_attrs) {
for (i = 0; shost->hostt->shost_attrs[i]; i++) {
error = class_attr_add(&shost->shost_dev,
shost->hostt->shost_attrs[i]);
if (error)
return error;
}
}
for (i = 0; scsi_sysfs_shost_attrs[i]; i++) {
if (!class_attr_overridden(shost->hostt->shost_attrs,
scsi_sysfs_shost_attrs[i])) {
error = device_create_file(&shost->shost_dev,
scsi_sysfs_shost_attrs[i]);
shost->hostt->shost_attrs[i]);
if (error)
return error;
}

View File

@ -1961,12 +1961,17 @@ fc_timed_out(struct scsi_cmnd *scmd)
}
/*
* Must be called with shost->host_lock held
* Called by fc_user_scan to locate an rport on the shost that
* matches the channel and target id, and invoke scsi_scan_target()
* on the rport.
*/
static int fc_user_scan(struct Scsi_Host *shost, uint channel,
uint id, uint lun)
static void
fc_user_scan_tgt(struct Scsi_Host *shost, uint channel, uint id, uint lun)
{
struct fc_rport *rport;
unsigned long flags;
spin_lock_irqsave(shost->host_lock, flags);
list_for_each_entry(rport, &fc_host_rports(shost), peers) {
if (rport->scsi_target_id == -1)
@ -1975,13 +1980,54 @@ static int fc_user_scan(struct Scsi_Host *shost, uint channel,
if (rport->port_state != FC_PORTSTATE_ONLINE)
continue;
if ((channel == SCAN_WILD_CARD || channel == rport->channel) &&
(id == SCAN_WILD_CARD || id == rport->scsi_target_id)) {
scsi_scan_target(&rport->dev, rport->channel,
rport->scsi_target_id, lun, 1);
if ((channel == rport->channel) &&
(id == rport->scsi_target_id)) {
spin_unlock_irqrestore(shost->host_lock, flags);
scsi_scan_target(&rport->dev, channel, id, lun, 1);
return;
}
}
spin_unlock_irqrestore(shost->host_lock, flags);
}
/*
* Called via sysfs scan routines. Necessary, as the FC transport
* wants to place all target objects below the rport object. So this
* routine must invoke the scsi_scan_target() routine with the rport
* object as the parent.
*/
static int
fc_user_scan(struct Scsi_Host *shost, uint channel, uint id, uint lun)
{
uint chlo, chhi;
uint tgtlo, tgthi;
if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) ||
((id != SCAN_WILD_CARD) && (id >= shost->max_id)) ||
((lun != SCAN_WILD_CARD) && (lun > shost->max_lun)))
return -EINVAL;
if (channel == SCAN_WILD_CARD) {
chlo = 0;
chhi = shost->max_channel + 1;
} else {
chlo = channel;
chhi = channel + 1;
}
if (id == SCAN_WILD_CARD) {
tgtlo = 0;
tgthi = shost->max_id;
} else {
tgtlo = id;
tgthi = id + 1;
}
for ( ; chlo < chhi; chlo++)
for ( ; tgtlo < tgthi; tgtlo++)
fc_user_scan_tgt(shost, chlo, tgtlo, lun);
return 0;
}

View File

@ -192,6 +192,16 @@ static void sas_non_host_smp_request(struct request_queue *q)
sas_smp_request(q, rphy_to_shost(rphy), rphy);
}
static void sas_host_release(struct device *dev)
{
struct Scsi_Host *shost = dev_to_shost(dev);
struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
struct request_queue *q = sas_host->q;
if (q)
blk_cleanup_queue(q);
}
static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy)
{
struct request_queue *q;
@ -199,6 +209,7 @@ static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy)
struct device *dev;
char namebuf[BUS_ID_SIZE];
const char *name;
void (*release)(struct device *);
if (!to_sas_internal(shost->transportt)->f->smp_handler) {
printk("%s can't handle SMP requests\n", shost->hostt->name);
@ -209,17 +220,19 @@ static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy)
q = blk_init_queue(sas_non_host_smp_request, NULL);
dev = &rphy->dev;
name = dev->bus_id;
release = NULL;
} else {
q = blk_init_queue(sas_host_smp_request, NULL);
dev = &shost->shost_gendev;
snprintf(namebuf, sizeof(namebuf),
"sas_host%d", shost->host_no);
name = namebuf;
release = sas_host_release;
}
if (!q)
return -ENOMEM;
error = bsg_register_queue(q, dev, name);
error = bsg_register_queue(q, dev, name, release);
if (error) {
blk_cleanup_queue(q);
return -ENOMEM;
@ -253,7 +266,6 @@ static void sas_bsg_remove(struct Scsi_Host *shost, struct sas_rphy *rphy)
return;
bsg_unregister_queue(q);
blk_cleanup_queue(q);
}
/*
@ -1301,6 +1313,9 @@ static void sas_expander_release(struct device *dev)
struct sas_rphy *rphy = dev_to_rphy(dev);
struct sas_expander_device *edev = rphy_to_expander_device(rphy);
if (rphy->q)
blk_cleanup_queue(rphy->q);
put_device(dev->parent);
kfree(edev);
}
@ -1310,6 +1325,9 @@ static void sas_end_device_release(struct device *dev)
struct sas_rphy *rphy = dev_to_rphy(dev);
struct sas_end_device *edev = rphy_to_end_device(rphy);
if (rphy->q)
blk_cleanup_queue(rphy->q);
put_device(dev->parent);
kfree(edev);
}

View File

@ -24,6 +24,7 @@
#include <linux/workqueue.h>
#include <linux/blkdev.h>
#include <linux/mutex.h>
#include <linux/sysfs.h>
#include <scsi/scsi.h>
#include "scsi_priv.h"
#include <scsi/scsi_device.h>
@ -1374,11 +1375,11 @@ static int spi_host_configure(struct transport_container *tc,
* overloads the return by setting 1<<1 if the attribute should
* be writeable */
#define TARGET_ATTRIBUTE_HELPER(name) \
(si->f->show_##name ? 1 : 0) + \
(si->f->set_##name ? 2 : 0)
(si->f->show_##name ? S_IRUGO : 0) | \
(si->f->set_##name ? S_IWUSR : 0)
static int target_attribute_is_visible(struct kobject *kobj,
struct attribute *attr, int i)
static mode_t target_attribute_is_visible(struct kobject *kobj,
struct attribute *attr, int i)
{
struct device *cdev = container_of(kobj, struct device, kobj);
struct scsi_target *starget = transport_class_to_starget(cdev);
@ -1428,7 +1429,7 @@ static int target_attribute_is_visible(struct kobject *kobj,
spi_support_ius(starget))
return TARGET_ATTRIBUTE_HELPER(hold_mcs);
else if (attr == &dev_attr_revalidate.attr)
return 1;
return S_IWUSR;
return 0;
}
@ -1462,25 +1463,9 @@ static int spi_target_configure(struct transport_container *tc,
struct device *cdev)
{
struct kobject *kobj = &cdev->kobj;
int i;
struct attribute *attr;
int rc;
for (i = 0; (attr = target_attributes[i]) != NULL; i++) {
int j = target_attribute_group.is_visible(kobj, attr, i);
/* FIXME: as well as returning -EEXIST, which we'd like
* to ignore, sysfs also does a WARN_ON and dumps a trace,
* which is bad, so temporarily, skip attributes that are
* already visible (the revalidate one) */
if (j && attr != &dev_attr_revalidate.attr)
rc = sysfs_add_file_to_group(kobj, attr,
target_attribute_group.name);
/* and make the attribute writeable if we have a set
* function */
if ((j & 1))
rc = sysfs_chmod_file(kobj, attr, attr->mode | S_IWUSR);
}
/* force an update based on parameters read from the device */
sysfs_update_group(kobj, &target_attribute_group);
return 0;
}

View File

@ -313,7 +313,8 @@ static struct platform_driver sgiwd93_driver = {
.probe = sgiwd93_probe,
.remove = __devexit_p(sgiwd93_remove),
.driver = {
.name = "sgiwd93"
.name = "sgiwd93",
.owner = THIS_MODULE,
}
};
@ -333,3 +334,4 @@ module_exit(sgiwd93_module_exit);
MODULE_DESCRIPTION("SGI WD33C93 driver");
MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:sgiwd93");

View File

@ -53,6 +53,7 @@
MODULE_AUTHOR("Thomas Bogendörfer");
MODULE_DESCRIPTION("SNI RM 53c710 SCSI Driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:snirm_53c710");
#define SNIRM710_CLOCK 32
@ -136,6 +137,7 @@ static struct platform_driver snirm710_driver = {
.remove = __devexit_p(snirm710_driver_remove),
.driver = {
.name = "snirm_53c710",
.owner = THIS_MODULE,
},
};

View File

@ -4322,7 +4322,7 @@ static void do_remove_sysfs_files(void)
static ssize_t
st_defined_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct st_modedef *STm = (struct st_modedef *)dev_get_drvdata(dev);
struct st_modedef *STm = dev_get_drvdata(dev);
ssize_t l = 0;
l = snprintf(buf, PAGE_SIZE, "%d\n", STm->defined);
@ -4334,7 +4334,7 @@ DEVICE_ATTR(defined, S_IRUGO, st_defined_show, NULL);
static ssize_t
st_defblk_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct st_modedef *STm = (struct st_modedef *)dev_get_drvdata(dev);
struct st_modedef *STm = dev_get_drvdata(dev);
ssize_t l = 0;
l = snprintf(buf, PAGE_SIZE, "%d\n", STm->default_blksize);
@ -4346,7 +4346,7 @@ DEVICE_ATTR(default_blksize, S_IRUGO, st_defblk_show, NULL);
static ssize_t
st_defdensity_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct st_modedef *STm = (struct st_modedef *)dev_get_drvdata(dev);
struct st_modedef *STm = dev_get_drvdata(dev);
ssize_t l = 0;
char *fmt;
@ -4361,7 +4361,7 @@ static ssize_t
st_defcompression_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct st_modedef *STm = (struct st_modedef *)dev_get_drvdata(dev);
struct st_modedef *STm = dev_get_drvdata(dev);
ssize_t l = 0;
l = snprintf(buf, PAGE_SIZE, "%d\n", STm->default_compression - 1);
@ -4373,7 +4373,7 @@ DEVICE_ATTR(default_compression, S_IRUGO, st_defcompression_show, NULL);
static ssize_t
st_options_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct st_modedef *STm = (struct st_modedef *)dev_get_drvdata(dev);
struct st_modedef *STm = dev_get_drvdata(dev);
struct scsi_tape *STp;
int i, j, options;
ssize_t l = 0;

View File

@ -294,6 +294,7 @@ static struct platform_driver esp_sun3x_driver = {
.remove = __devexit_p(esp_sun3x_remove),
.driver = {
.name = "sun3x_esp",
.owner = THIS_MODULE,
},
};
@ -314,3 +315,4 @@ MODULE_VERSION(DRV_VERSION);
module_init(sun3x_esp_init);
module_exit(sun3x_esp_exit);
MODULE_ALIAS("platform:sun3x_esp");

View File

@ -1715,13 +1715,12 @@ static void flush_dev(struct scsi_device *dev, unsigned long cursec, unsigned in
}
static irqreturn_t ihdlr(int irq, unsigned int j) {
static irqreturn_t ihdlr(unsigned int j)
{
struct scsi_cmnd *SCpnt;
unsigned int i, k, c, status, tstatus, reg, ret;
struct mscp *spp, *cpp;
if (sh[j]->irq != irq)
panic("%s: ihdlr, irq %d, sh[j]->irq %d.\n", BN(j), irq, sh[j]->irq);
int irq = sh[j]->irq;
/* Check if this board need to be serviced */
if (!((reg = inb(sh[j]->io_port + REG_SYS_INTR)) & IRQ_ASSERTED)) goto none;
@ -1935,7 +1934,7 @@ static irqreturn_t do_interrupt_handler(int irq, void *shap) {
if ((j = (unsigned int)((char *)shap - sha)) >= num_boards) return IRQ_NONE;
spin_lock_irqsave(sh[j]->host_lock, spin_flags);
ret = ihdlr(irq, j);
ret = ihdlr(j);
spin_unlock_irqrestore(sh[j]->host_lock, spin_flags);
return ret;
}

View File

@ -477,11 +477,10 @@ const struct file_operations sysfs_file_operations = {
.poll = sysfs_poll,
};
int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr,
int type)
int sysfs_add_file_mode(struct sysfs_dirent *dir_sd,
const struct attribute *attr, int type, mode_t amode)
{
umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG;
umode_t mode = (amode & S_IALLUGO) | S_IFREG;
struct sysfs_addrm_cxt acxt;
struct sysfs_dirent *sd;
int rc;
@ -502,6 +501,13 @@ int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr,
}
int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr,
int type)
{
return sysfs_add_file_mode(dir_sd, attr, type, attr->mode);
}
/**
* sysfs_create_file - create an attribute file for an object.
* @kobj: object we're creating for.

View File

@ -23,35 +23,50 @@ static void remove_files(struct sysfs_dirent *dir_sd, struct kobject *kobj,
int i;
for (i = 0, attr = grp->attrs; *attr; i++, attr++)
if (!grp->is_visible ||
grp->is_visible(kobj, *attr, i))
sysfs_hash_and_remove(dir_sd, (*attr)->name);
sysfs_hash_and_remove(dir_sd, (*attr)->name);
}
static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj,
const struct attribute_group *grp)
const struct attribute_group *grp, int update)
{
struct attribute *const* attr;
int error = 0, i;
for (i = 0, attr = grp->attrs; *attr && !error; i++, attr++)
if (!grp->is_visible ||
grp->is_visible(kobj, *attr, i))
error |=
sysfs_add_file(dir_sd, *attr, SYSFS_KOBJ_ATTR);
for (i = 0, attr = grp->attrs; *attr && !error; i++, attr++) {
mode_t mode = 0;
/* in update mode, we're changing the permissions or
* visibility. Do this by first removing then
* re-adding (if required) the file */
if (update)
sysfs_hash_and_remove(dir_sd, (*attr)->name);
if (grp->is_visible) {
mode = grp->is_visible(kobj, *attr, i);
if (!mode)
continue;
}
error = sysfs_add_file_mode(dir_sd, *attr, SYSFS_KOBJ_ATTR,
(*attr)->mode | mode);
if (unlikely(error))
break;
}
if (error)
remove_files(dir_sd, kobj, grp);
return error;
}
int sysfs_create_group(struct kobject * kobj,
const struct attribute_group * grp)
static int internal_create_group(struct kobject *kobj, int update,
const struct attribute_group *grp)
{
struct sysfs_dirent *sd;
int error;
BUG_ON(!kobj || !kobj->sd);
BUG_ON(!kobj || (!update && !kobj->sd));
/* Updates may happen before the object has been instantiated */
if (unlikely(update && !kobj->sd))
return -EINVAL;
if (grp->name) {
error = sysfs_create_subdir(kobj, grp->name, &sd);
@ -60,7 +75,7 @@ int sysfs_create_group(struct kobject * kobj,
} else
sd = kobj->sd;
sysfs_get(sd);
error = create_files(sd, kobj, grp);
error = create_files(sd, kobj, grp, update);
if (error) {
if (grp->name)
sysfs_remove_subdir(sd);
@ -69,6 +84,47 @@ int sysfs_create_group(struct kobject * kobj,
return error;
}
/**
* sysfs_create_group - given a directory kobject, create an attribute group
* @kobj: The kobject to create the group on
* @grp: The attribute group to create
*
* This function creates a group for the first time. It will explicitly
* warn and error if any of the attribute files being created already exist.
*
* Returns 0 on success or error.
*/
int sysfs_create_group(struct kobject *kobj,
const struct attribute_group *grp)
{
return internal_create_group(kobj, 0, grp);
}
/**
* sysfs_update_group - given a directory kobject, create an attribute group
* @kobj: The kobject to create the group on
* @grp: The attribute group to create
*
* This function updates an attribute group. Unlike
* sysfs_create_group(), it will explicitly not warn or error if any
* of the attribute files being created already exist. Furthermore,
* if the visibility of the files has changed through the is_visible()
* callback, it will update the permissions and add or remove the
* relevant files.
*
* The primary use for this function is to call it after making a change
* that affects group visibility.
*
* Returns 0 on success or error.
*/
int sysfs_update_group(struct kobject *kobj,
const struct attribute_group *grp)
{
return internal_create_group(kobj, 1, grp);
}
void sysfs_remove_group(struct kobject * kobj,
const struct attribute_group * grp)
{
@ -95,4 +151,5 @@ void sysfs_remove_group(struct kobject * kobj,
EXPORT_SYMBOL_GPL(sysfs_create_group);
EXPORT_SYMBOL_GPL(sysfs_update_group);
EXPORT_SYMBOL_GPL(sysfs_remove_group);

View File

@ -154,6 +154,8 @@ extern const struct file_operations sysfs_file_operations;
int sysfs_add_file(struct sysfs_dirent *dir_sd,
const struct attribute *attr, int type);
int sysfs_add_file_mode(struct sysfs_dirent *dir_sd,
const struct attribute *attr, int type, mode_t amode);
/*
* bin.c
*/

View File

@ -56,19 +56,25 @@ struct sg_io_v4 {
#if defined(CONFIG_BLK_DEV_BSG)
struct bsg_class_device {
struct device *class_dev;
struct device *dev;
struct device *parent;
int minor;
struct request_queue *queue;
struct kref ref;
void (*release)(struct device *);
};
extern int bsg_register_queue(struct request_queue *, struct device *, const char *);
extern int bsg_register_queue(struct request_queue *q,
struct device *parent, const char *name,
void (*release)(struct device *));
extern void bsg_unregister_queue(struct request_queue *);
#else
static inline int bsg_register_queue(struct request_queue * rq, struct device *dev, const char *name)
static inline int bsg_register_queue(struct request_queue *q,
struct device *parent, const char *name,
void (*release)(struct device *))
{
return 0;
}
static inline void bsg_unregister_queue(struct request_queue *rq)
static inline void bsg_unregister_queue(struct request_queue *q)
{
}
#endif

View File

@ -32,7 +32,7 @@ struct attribute {
struct attribute_group {
const char *name;
int (*is_visible)(struct kobject *,
mode_t (*is_visible)(struct kobject *,
struct attribute *, int);
struct attribute **attrs;
};
@ -105,6 +105,8 @@ void sysfs_remove_link(struct kobject *kobj, const char *name);
int __must_check sysfs_create_group(struct kobject *kobj,
const struct attribute_group *grp);
int sysfs_update_group(struct kobject *kobj,
const struct attribute_group *grp);
void sysfs_remove_group(struct kobject *kobj,
const struct attribute_group *grp);
int sysfs_add_file_to_group(struct kobject *kobj,

View File

@ -181,7 +181,8 @@ struct scsi_device {
sdev_printk(prefix, (scmd)->device, fmt, ##a)
enum scsi_target_state {
STARGET_RUNNING = 1,
STARGET_CREATED = 1,
STARGET_RUNNING,
STARGET_DEL,
};