#include <linux/delay.h>
#include <linux/ctype.h>
#include <linux/blkdev.h>
-#include <asm/io.h>
-#include "scsi.h"
-#include "hosts.h"
-#include "dc395x.h"
-#include <scsi/scsicam.h> /* needed for scsicam_bios_param */
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/pci.h>
#include <linux/list.h>
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsicam.h> /* needed for scsicam_bios_param */
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+
+#include "dc395x.h"
#define DC395X_NAME "dc395x"
#define DC395X_BANNER "Tekram DC395(U/UW/F), DC315(U) - ASIC TRM-S1040"
struct ScsiReqBlk {
struct list_head list; /* next/prev ptrs for srb lists */
struct DeviceCtlBlk *dcb;
- Scsi_Cmnd *cmd;
+ struct scsi_cmnd *cmd;
struct SGentry *segment_x; /* Linear array of hw sg entries (up to 64 entries) */
- u32 sg_bus_addr; /* Bus address of sg list (ie, of segment_x) */
+ dma_addr_t sg_bus_addr; /* Bus address of sg list (ie, of segment_x) */
u8 sg_count; /* No of HW sg entries for this request */
u8 sg_index; /* Index of HW sg entry for this request */
- u32 total_xfer_length; /* Total number of bytes remaining to be transfered */
- unsigned char *virt_addr; /* Virtual address of current transfer position */
-
+ size_t total_xfer_length; /* Total number of bytes remaining to be transfered */
+ size_t request_length; /* Total number of bytes in this request */
/*
* The sense buffer handling function, request_sense, uses
* the first hw sg entry (segment_x[0]) and the transfer
* total_xfer_length in xferred. These values are restored in
* pci_unmap_srb_sense. This is the only place xferred is used.
*/
- u32 xferred; /* Saved copy of total_xfer_length */
+ size_t xferred; /* Saved copy of total_xfer_length */
u16 state;
struct AdapterCtlBlk {
struct Scsi_Host *scsi_host;
- u16 io_port_base;
- u16 io_port_len;
+ unsigned long io_port_base;
+ unsigned long io_port_len;
struct list_head dcb_list; /* head of going dcb list */
struct DeviceCtlBlk *dcb_run_robin;
u8 sel_timeout;
- u8 irq_level;
+ unsigned int irq_level;
u8 tag_max_num;
u8 acb_flag;
u8 gmode2;
static void reselect(struct AdapterCtlBlk *acb);
static u8 start_scsi(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
struct ScsiReqBlk *srb);
-static void build_srb(Scsi_Cmnd *cmd, struct DeviceCtlBlk *dcb,
+static inline void enable_msgout_abort(struct AdapterCtlBlk *acb,
+ struct ScsiReqBlk *srb);
+static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb,
struct ScsiReqBlk *srb);
static void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_code,
- Scsi_Cmnd *cmd, u8 force);
+ struct scsi_cmnd *cmd, u8 force);
static void scsi_reset_detect(struct AdapterCtlBlk *acb);
static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb);
static void pci_unmap_srb_sense(struct AdapterCtlBlk *acb,
struct ScsiReqBlk *srb);
-static inline void enable_msgout_abort(struct AdapterCtlBlk *acb,
- struct ScsiReqBlk *srb);
static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
struct ScsiReqBlk *srb);
static void request_sense(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
struct ScsiReqBlk *srb);
-static inline void set_xfer_rate(struct AdapterCtlBlk *acb,
+static void set_xfer_rate(struct AdapterCtlBlk *acb,
struct DeviceCtlBlk *dcb);
static void waiting_timeout(unsigned long ptr);
int def; /* default value */
int safe; /* safe value */
};
-static struct ParameterData __initdata cfg_data[] = {
+static struct ParameterData __devinitdata cfg_data[] = {
{ /* adapter id */
CFG_PARAM_UNSET,
0,
* set_safe_settings - if the use_safe_settings option is set then
* set all values to the safe and slow values.
**/
-static void __init set_safe_settings(void)
+static void __devinit set_safe_settings(void)
{
if (use_safe_settings)
{
* fix_settings - reset any boot parameters which are out of range
* back to the default values.
**/
-static void __init fix_settings(void)
+static void __devinit fix_settings(void)
{
int i;
* Mapping from the eeprom delay index value (index into this array)
* to the the number of actual seconds that the delay should be for.
*/
-static char __initdata eeprom_index_to_delay_map[] =
+static char __devinitdata eeprom_index_to_delay_map[] =
{ 1, 3, 5, 10, 16, 30, 60, 120 };
*
* @eeprom: The eeprom structure in which we find the delay index to map.
**/
-static void __init eeprom_index_to_delay(struct NvRamType *eeprom)
+static void __devinit eeprom_index_to_delay(struct NvRamType *eeprom)
{
eeprom->delay_time = eeprom_index_to_delay_map[eeprom->delay_time];
}
*
* @delay: The delay, in seconds, to find the eeprom index for.
**/
-static int __init delay_to_eeprom_index(int delay)
+static int __devinit delay_to_eeprom_index(int delay)
{
u8 idx = 0;
while (idx < 7 && eeprom_index_to_delay_map[idx] < delay)
*
* @eeprom: The eeprom data to override with command line options.
**/
-static void __init eeprom_override(struct NvRamType *eeprom)
+static void __devinit eeprom_override(struct NvRamType *eeprom)
{
u8 id;
/* Find cmd in SRB list */
-inline static struct ScsiReqBlk *find_cmd(Scsi_Cmnd *cmd,
+static inline struct ScsiReqBlk *find_cmd(struct scsi_cmnd *cmd,
struct list_head *head)
{
struct ScsiReqBlk *i;
}
}
-
/* Prepare SRB for being sent to Device DCB w/ command *cmd */
-static void build_srb(Scsi_Cmnd *cmd, struct DeviceCtlBlk *dcb,
+static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb,
struct ScsiReqBlk *srb)
{
- int dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
+ enum dma_data_direction dir = cmd->sc_data_direction;
dprintkdbg(DBG_0, "build_srb: (pid#%li) <%02i-%i>\n",
cmd->pid, dcb->target_id, dcb->target_lun);
srb->sg_count = 0;
srb->total_xfer_length = 0;
srb->sg_bus_addr = 0;
- srb->virt_addr = 0;
srb->sg_index = 0;
srb->adapter_status = 0;
srb->target_status = 0;
reqlen, cmd->request_buffer, cmd->use_sg,
srb->sg_count);
- srb->virt_addr = page_address(sl->page);
for (i = 0; i < srb->sg_count; i++) {
u32 busaddr = (u32)sg_dma_address(&sl[i]);
u32 seglen = (u32)sl[i].length;
srb->total_xfer_length++;
srb->segment_x[0].length = srb->total_xfer_length;
- srb->virt_addr = cmd->request_buffer;
+
dprintkdbg(DBG_0,
"build_srb: [1] len=%d buf=%p use_sg=%d map=%08x\n",
srb->total_xfer_length, cmd->request_buffer,
cmd->use_sg, srb->segment_x[0].address);
}
+
+ srb->request_length = srb->total_xfer_length;
}
* and is expected to be held on return.
*
**/
-static int dc395x_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
+static int dc395x_queue_command(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
{
struct DeviceCtlBlk *dcb;
struct ScsiReqBlk *srb;
srb, srb->cmd, srb->cmd->pid,
srb->cmd->cmnd[0], srb->cmd->device->id,
srb->cmd->device->lun);
- printk(" sglist=%p cnt=%i idx=%i len=%i\n",
+ printk(" sglist=%p cnt=%i idx=%i len=%zu\n",
srb->segment_x, srb->sg_count, srb->sg_index,
srb->total_xfer_length);
printk(" state=0x%04x status=0x%02x phase=0x%02x (%sconn.)\n",
* @cmd - some command for this host (for fetching hooks)
* Returns: SUCCESS (0x2002) on success, else FAILED (0x2003).
*/
-static int dc395x_eh_bus_reset(Scsi_Cmnd *cmd)
+static int __dc395x_eh_bus_reset(struct scsi_cmnd *cmd)
{
struct AdapterCtlBlk *acb =
(struct AdapterCtlBlk *)cmd->device->host->hostdata;
return SUCCESS;
}
+static int dc395x_eh_bus_reset(struct scsi_cmnd *cmd)
+{
+ int rc;
+
+ spin_lock_irq(cmd->device->host->host_lock);
+ rc = __dc395x_eh_bus_reset(cmd);
+ spin_unlock_irq(cmd->device->host->host_lock);
+
+ return rc;
+}
/*
* abort an errant SCSI command
* @cmd - command to be aborted
* Returns: SUCCESS (0x2002) on success, else FAILED (0x2003).
*/
-static int dc395x_eh_abort(Scsi_Cmnd *cmd)
+static int dc395x_eh_abort(struct scsi_cmnd *cmd)
{
/*
* Look into our command queues: If it has not been sent already,
}
srb = find_cmd(cmd, &dcb->srb_going_list);
if (srb) {
- dprintkl(KERN_DEBUG, "eh_abort: Command in progress");
+ dprintkl(KERN_DEBUG, "eh_abort: Command in progress\n");
/* XXX: Should abort the command here */
} else {
- dprintkl(KERN_DEBUG, "eh_abort: Command not found");
+ dprintkl(KERN_DEBUG, "eh_abort: Command not found\n");
}
return FAILED;
}
}
+#define DC395x_ENABLE_MSGOUT \
+ DC395x_write16 (acb, TRM_S1040_SCSI_CONTROL, DO_SETATN); \
+ srb->state |= SRB_MSGOUT
+
+
+/* abort command */
+static inline void enable_msgout_abort(struct AdapterCtlBlk *acb,
+ struct ScsiReqBlk *srb)
+{
+ srb->msgout_buf[0] = ABORT;
+ srb->msg_count = 1;
+ DC395x_ENABLE_MSGOUT;
+ srb->state &= ~SRB_MSGIN;
+ srb->state |= SRB_MSGOUT;
+}
+
+
/**
* dc395x_handle_interrupt - Handle an interrupt that has been confirmed to
* have been triggered for this card.
}
-static irqreturn_t dc395x_interrupt(int irq, void *dev_id,
- struct pt_regs *regs)
+static irqreturn_t dc395x_interrupt(int irq, void *dev_id)
{
- struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)dev_id;
+ struct AdapterCtlBlk *acb = dev_id;
u16 scsi_status;
u8 dma_status;
irqreturn_t handled = IRQ_NONE;
/*
* Compute the next Scatter Gather list index and adjust its length
- * and address if necessary; also compute virt_addr
+ * and address if necessary
*/
static void sg_update_list(struct ScsiReqBlk *srb, u32 left)
{
u8 idx;
- struct scatterlist *sg;
- Scsi_Cmnd *cmd = srb->cmd;
- int segment = cmd->use_sg;
u32 xferred = srb->total_xfer_length - left; /* bytes transfered */
struct SGentry *psge = srb->segment_x + srb->sg_index;
psge++;
}
sg_verify_length(srb);
-
- /* we need the corresponding virtual address */
- if (!segment) {
- srb->virt_addr += xferred;
- return;
- }
-
- /* We have to walk the scatterlist to find it */
- sg = (struct scatterlist *)cmd->request_buffer;
- while (segment--) {
- unsigned long mask =
- ~((unsigned long)sg->length - 1) & PAGE_MASK;
- if ((sg_dma_address(sg) & mask) == (psge->address & mask)) {
- srb->virt_addr = (page_address(sg->page)
- + psge->address -
- (psge->address & PAGE_MASK));
- return;
- }
- ++sg;
- }
-
- dprintkl(KERN_ERR, "sg_update_list: sg_to_virt failed\n");
- srb->virt_addr = 0;
}
*/
static void sg_subtract_one(struct ScsiReqBlk *srb)
{
- srb->total_xfer_length--;
- srb->segment_x[srb->sg_index].length--;
- if (srb->total_xfer_length &&
- !srb->segment_x[srb->sg_index].length) {
- if (debug_enabled(DBG_PIO))
- printk(" (next segment)");
- srb->sg_index++;
- sg_update_list(srb, srb->total_xfer_length);
- }
+ sg_update_list(srb, srb->total_xfer_length - 1);
}
* If we need more data, the DMA SG list will be freshly set up, anyway
*/
dprintkdbg(DBG_PIO, "data_out_phase0: "
- "DMA{fifcnt=0x%02x fifostat=0x%02x} "
+ "DMA{fifocnt=0x%02x fifostat=0x%02x} "
"SCSI{fifocnt=0x%02x cnt=0x%06x status=0x%04x} total=0x%06x\n",
DC395x_read8(acb, TRM_S1040_DMA_FIFOCNT),
DC395x_read8(acb, TRM_S1040_DMA_FIFOSTAT),
data_io_transfer(acb, srb, XFERDATAOUT);
}
-
static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
u16 *pscsi_status)
{
u16 scsi_status = *pscsi_status;
- u32 d_left_counter = 0;
+
dprintkdbg(DBG_0, "data_in_phase0: (pid#%li) <%02i-%i>\n",
srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun);
* seem to be a bad idea, actually.
*/
if (!(srb->state & SRB_XFERPAD)) {
+ u32 d_left_counter;
+ unsigned int sc, fc;
+
if (scsi_status & PARITYERROR) {
dprintkl(KERN_INFO, "data_in_phase0: (pid#%li) "
"Parity Error\n", srb->cmd->pid);
DC395x_read8(acb, TRM_S1040_DMA_FIFOSTAT));
}
/* Now: Check remainig data: The SCSI counters should tell us ... */
- d_left_counter = DC395x_read32(acb, TRM_S1040_SCSI_COUNTER)
- + ((DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) & 0x1f)
+ sc = DC395x_read32(acb, TRM_S1040_SCSI_COUNTER);
+ fc = DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT);
+ d_left_counter = sc + ((fc & 0x1f)
<< ((srb->dcb->sync_period & WIDE_SYNC) ? 1 :
0));
dprintkdbg(DBG_KG, "data_in_phase0: "
"SCSI{fifocnt=0x%02x%s ctr=0x%08x} "
"DMA{fifocnt=0x%02x fifostat=0x%02x ctr=0x%08x} "
"Remain{totxfer=%i scsi_fifo+ctr=%i}\n",
- DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT),
+ fc,
(srb->dcb->sync_period & WIDE_SYNC) ? "words" : "bytes",
- DC395x_read32(acb, TRM_S1040_SCSI_COUNTER),
- DC395x_read8(acb, TRM_S1040_DMA_FIFOCNT),
+ sc,
+ fc,
DC395x_read8(acb, TRM_S1040_DMA_FIFOSTAT),
DC395x_read32(acb, TRM_S1040_DMA_CXCNT),
srb->total_xfer_length, d_left_counter);
/* KG: Less than or equal to 4 bytes can not be transfered via DMA, it seems. */
if (d_left_counter
&& srb->total_xfer_length <= DC395x_LASTPIO) {
+ size_t left_io = srb->total_xfer_length;
+
/*u32 addr = (srb->segment_x[srb->sg_index].address); */
/*sg_update_list (srb, d_left_counter); */
- dprintkdbg(DBG_PIO, "data_in_phase0: PIO (%i %s) to "
- "%p for remaining %i bytes:",
- DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) & 0x1f,
+ dprintkdbg(DBG_PIO, "data_in_phase0: PIO (%i %s) "
+ "for remaining %i bytes:",
+ fc & 0x1f,
(srb->dcb->sync_period & WIDE_SYNC) ?
"words" : "bytes",
- srb->virt_addr,
srb->total_xfer_length);
if (srb->dcb->sync_period & WIDE_SYNC)
DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2,
CFG2_WIDEFIFO);
- while (DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) != 0x40) {
- u8 byte = DC395x_read8(acb, TRM_S1040_SCSI_FIFO);
- *(srb->virt_addr)++ = byte;
- if (debug_enabled(DBG_PIO))
- printk(" %02x", byte);
- d_left_counter--;
- sg_subtract_one(srb);
- }
- if (srb->dcb->sync_period & WIDE_SYNC) {
-#if 1
- /* Read the last byte ... */
- if (srb->total_xfer_length > 0) {
- u8 byte = DC395x_read8(acb, TRM_S1040_SCSI_FIFO);
- *(srb->virt_addr)++ = byte;
- srb->total_xfer_length--;
+ while (left_io) {
+ unsigned char *virt, *base = NULL;
+ unsigned long flags = 0;
+ size_t len = left_io;
+
+ if (srb->cmd->use_sg) {
+ size_t offset = srb->request_length - left_io;
+ local_irq_save(flags);
+ /* Assumption: it's inside one page as it's at most 4 bytes and
+ I just assume it's on a 4-byte boundary */
+ base = scsi_kmap_atomic_sg((struct scatterlist *)srb->cmd->request_buffer,
+ srb->sg_count, &offset, &len);
+ virt = base + offset;
+ } else {
+ virt = srb->cmd->request_buffer + srb->cmd->request_bufflen - left_io;
+ len = left_io;
+ }
+ left_io -= len;
+
+ while (len) {
+ u8 byte;
+ byte = DC395x_read8(acb, TRM_S1040_SCSI_FIFO);
+ *virt++ = byte;
+
if (debug_enabled(DBG_PIO))
printk(" %02x", byte);
+
+ d_left_counter--;
+ sg_subtract_one(srb);
+
+ len--;
+
+ fc = DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT);
+
+ if (fc == 0x40) {
+ left_io = 0;
+ break;
+ }
+ }
+
+ WARN_ON((fc != 0x40) == !d_left_counter);
+
+ if (fc == 0x40 && (srb->dcb->sync_period & WIDE_SYNC)) {
+ /* Read the last byte ... */
+ if (srb->total_xfer_length > 0) {
+ u8 byte = DC395x_read8(acb, TRM_S1040_SCSI_FIFO);
+
+ *virt++ = byte;
+ srb->total_xfer_length--;
+ if (debug_enabled(DBG_PIO))
+ printk(" %02x", byte);
+ }
+
+ DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2, 0);
+ }
+
+ if (srb->cmd->use_sg) {
+ scsi_kunmap_atomic_sg(base);
+ local_irq_restore(flags);
}
-#endif
- DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2, 0);
}
/*printk(" %08x", *(u32*)(bus_to_virt (addr))); */
/*srb->total_xfer_length = 0; */
SCMD_FIFO_IN);
} else { /* write */
int ln = srb->total_xfer_length;
+ size_t left_io = srb->total_xfer_length;
+
if (srb->dcb->sync_period & WIDE_SYNC)
DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2,
CFG2_WIDEFIFO);
- dprintkdbg(DBG_PIO,
- "data_io_transfer: PIO %i bytes from %p:",
- srb->total_xfer_length, srb->virt_addr);
- while (srb->total_xfer_length) {
- if (debug_enabled(DBG_PIO))
- printk(" %02x", (unsigned char) *(srb->virt_addr));
+ while (left_io) {
+ unsigned char *virt, *base = NULL;
+ unsigned long flags = 0;
+ size_t len = left_io;
+
+ if (srb->cmd->use_sg) {
+ size_t offset = srb->request_length - left_io;
+ local_irq_save(flags);
+ /* Again, max 4 bytes */
+ base = scsi_kmap_atomic_sg((struct scatterlist *)srb->cmd->request_buffer,
+ srb->sg_count, &offset, &len);
+ virt = base + offset;
+ } else {
+ virt = srb->cmd->request_buffer + srb->cmd->request_bufflen - left_io;
+ len = left_io;
+ }
+ left_io -= len;
- DC395x_write8(acb, TRM_S1040_SCSI_FIFO,
- *(srb->virt_addr)++);
+ while (len--) {
+ if (debug_enabled(DBG_PIO))
+ printk(" %02x", *virt);
- sg_subtract_one(srb);
+ DC395x_write8(acb, TRM_S1040_SCSI_FIFO, *virt++);
+
+ sg_subtract_one(srb);
+ }
+
+ if (srb->cmd->use_sg) {
+ scsi_kunmap_atomic_sg(base);
+ local_irq_restore(flags);
+ }
}
if (srb->dcb->sync_period & WIDE_SYNC) {
if (ln % 2) {
return 1;
}
-#define DC395x_ENABLE_MSGOUT \
- DC395x_write16 (acb, TRM_S1040_SCSI_CONTROL, DO_SETATN); \
- srb->state |= SRB_MSGOUT
-
-
/* reject_msg */
static inline void msgin_reject(struct AdapterCtlBlk *acb,
struct ScsiReqBlk *srb)
}
-/* abort command */
-static inline void enable_msgout_abort(struct AdapterCtlBlk *acb,
- struct ScsiReqBlk *srb)
-{
- srb->msgout_buf[0] = ABORT;
- srb->msg_count = 1;
- DC395x_ENABLE_MSGOUT;
- srb->state &= ~SRB_MSGIN;
- srb->state |= SRB_MSGOUT;
-}
-
-
static struct ScsiReqBlk *msgin_qtag(struct AdapterCtlBlk *acb,
struct DeviceCtlBlk *dcb, u8 tag)
{
/* unmap mapped pci regions from SRB */
static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb)
{
- Scsi_Cmnd *cmd = srb->cmd;
- int dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
+ struct scsi_cmnd *cmd = srb->cmd;
+ enum dma_data_direction dir = cmd->sc_data_direction;
if (cmd->use_sg && dir != PCI_DMA_NONE) {
/* unmap DC395x SG list */
dprintkdbg(DBG_SG, "pci_unmap_srb: list=%08x(%05x)\n",
struct ScsiReqBlk *srb)
{
u8 tempcnt, status;
- Scsi_Cmnd *cmd = srb->cmd;
- struct ScsiInqData *ptr;
- int dir;
-
- dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
- if (cmd->use_sg) {
- struct scatterlist* sg = (struct scatterlist *)cmd->request_buffer;
- ptr = (struct ScsiInqData *)(page_address(sg->page) + sg->offset);
- } else {
- ptr = (struct ScsiInqData *)(cmd->request_buffer);
- }
+ struct scsi_cmnd *cmd = srb->cmd;
+ enum dma_data_direction dir = cmd->sc_data_direction;
+ int ckc_only = 1;
dprintkdbg(DBG_1, "srb_done: (pid#%li) <%02i-%i>\n", srb->cmd->pid,
srb->cmd->device->id, srb->cmd->device->lun);
- dprintkdbg(DBG_SG, "srb_done: srb=%p sg=%i(%i/%i) buf=%p addr=%p\n",
+ dprintkdbg(DBG_SG, "srb_done: srb=%p sg=%i(%i/%i) buf=%p\n",
srb, cmd->use_sg, srb->sg_index, srb->sg_count,
- cmd->request_buffer, ptr);
+ cmd->request_buffer);
status = srb->target_status;
if (srb->flag & AUTO_REQSENSE) {
dprintkdbg(DBG_0, "srb_done: AUTO_REQSENSE1\n");
srb->segment_x[0].address,
cmd->request_bufflen, dir);
}
-
- if ((cmd->result & RES_DID) == 0 && cmd->cmnd[0] == INQUIRY
- && cmd->cmnd[2] == 0 && cmd->request_bufflen >= 8
- && dir != PCI_DMA_NONE && ptr && (ptr->Vers & 0x07) >= 2)
- dcb->inquiry7 = ptr->Flags;
+ ckc_only = 0;
/* Check Error Conditions */
ckc_e:
+ if (cmd->cmnd[0] == INQUIRY) {
+ unsigned char *base = NULL;
+ struct ScsiInqData *ptr;
+ unsigned long flags = 0;
+
+ if (cmd->use_sg) {
+ struct scatterlist* sg = (struct scatterlist *)cmd->request_buffer;
+ size_t offset = 0, len = sizeof(struct ScsiInqData);
+
+ local_irq_save(flags);
+ base = scsi_kmap_atomic_sg(sg, cmd->use_sg, &offset, &len);
+ ptr = (struct ScsiInqData *)(base + offset);
+ } else
+ ptr = (struct ScsiInqData *)(cmd->request_buffer);
+
+ if (!ckc_only && (cmd->result & RES_DID) == 0
+ && cmd->cmnd[2] == 0 && cmd->request_bufflen >= 8
+ && dir != PCI_DMA_NONE && ptr && (ptr->Vers & 0x07) >= 2)
+ dcb->inquiry7 = ptr->Flags;
+
/*if( srb->cmd->cmnd[0] == INQUIRY && */
/* (host_byte(cmd->result) == DID_OK || status_byte(cmd->result) & CHECK_CONDITION) ) */
- if (cmd->cmnd[0] == INQUIRY && (cmd->result == (DID_OK << 16)
- || status_byte(cmd->
- result) &
- CHECK_CONDITION)) {
-
- if (!dcb->init_tcq_flag) {
- add_dev(acb, dcb, ptr);
- dcb->init_tcq_flag = 1;
+ if ((cmd->result == (DID_OK << 16)
+ || status_byte(cmd->result) &
+ CHECK_CONDITION)) {
+ if (!dcb->init_tcq_flag) {
+ add_dev(acb, dcb, ptr);
+ dcb->init_tcq_flag = 1;
+ }
}
+ if (cmd->use_sg) {
+ scsi_kunmap_atomic_sg(base);
+ local_irq_restore(flags);
+ }
}
-
/* Here is the info for Doug Gilbert's sg3 ... */
cmd->resid = srb->total_xfer_length;
/* This may be interpreted by sb. or not ... */
/* abort all cmds in our queues */
static void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_flag,
- Scsi_Cmnd *cmd, u8 force)
+ struct scsi_cmnd *cmd, u8 force)
{
struct DeviceCtlBlk *dcb;
dprintkl(KERN_INFO, "doing_srb_done: pids ");
list_for_each_entry(dcb, &acb->dcb_list, list) {
struct ScsiReqBlk *srb;
struct ScsiReqBlk *tmp;
- Scsi_Cmnd *p;
+ struct scsi_cmnd *p;
list_for_each_entry_safe(srb, tmp, &dcb->srb_going_list, list) {
+ enum dma_data_direction dir;
int result;
- int dir;
p = srb->cmd;
- dir = scsi_to_pci_dma_dir(p->sc_data_direction);
+ dir = p->sc_data_direction;
result = MK_RES(0, did_flag, 0, 0);
printk("G:%li(%02i-%i) ", p->pid,
p->device->id, p->device->lun);
} else {
acb->acb_flag |= RESET_DETECT;
reset_dev_param(acb);
- doing_srb_done(acb, DID_RESET, 0, 1);
+ doing_srb_done(acb, DID_RESET, NULL, 1);
/*DC395x_RecoverSRB( acb ); */
acb->active_dcb = NULL;
acb->acb_flag = 0;
static void request_sense(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
struct ScsiReqBlk *srb)
{
- Scsi_Cmnd *cmd = srb->cmd;
+ struct scsi_cmnd *cmd = srb->cmd;
dprintkdbg(DBG_1, "request_sense: (pid#%li) <%02i-%i>\n",
cmd->pid, cmd->device->id, cmd->device->lun);
* @target: The target for the new device.
* @lun: The lun for the new device.
*
- * Return the new device if succesfull or NULL on failure.
+ * Return the new device if successful or NULL on failure.
**/
static struct DeviceCtlBlk *device_alloc(struct AdapterCtlBlk *acb,
u8 target, u8 lun)
*
* @io_port: base I/O address
**/
-static void __init trms1040_wait_30us(u16 io_port)
+static void __devinit trms1040_wait_30us(unsigned long io_port)
{
/* ScsiPortStallExecution(30); wait 30 us */
outb(5, io_port + TRM_S1040_GEN_TIMER);
* @cmd: SB + op code (command) to send
* @addr: address to send
**/
-static void __init trms1040_write_cmd(u16 io_port, u8 cmd, u8 addr)
+static void __devinit trms1040_write_cmd(unsigned long io_port, u8 cmd, u8 addr)
{
int i;
u8 send_data;
* @addr: offset into EEPROM
* @byte: bytes to write
**/
-static void __init trms1040_set_data(u16 io_port, u8 addr, u8 byte)
+static void __devinit trms1040_set_data(unsigned long io_port, u8 addr, u8 byte)
{
int i;
u8 send_data;
* @eeprom: the data to write
* @io_port: the base io port
**/
-static void __init trms1040_write_all(struct NvRamType *eeprom, u16 io_port)
+static void __devinit trms1040_write_all(struct NvRamType *eeprom, unsigned long io_port)
{
u8 *b_eeprom = (u8 *)eeprom;
u8 addr;
*
* Returns the the byte read.
**/
-static u8 __init trms1040_get_data(u16 io_port, u8 addr)
+static u8 __devinit trms1040_get_data(unsigned long io_port, u8 addr)
{
int i;
u8 read_byte;
* @eeprom: where to store the data
* @io_port: the base io port
**/
-static void __init trms1040_read_all(struct NvRamType *eeprom, u16 io_port)
+static void __devinit trms1040_read_all(struct NvRamType *eeprom, unsigned long io_port)
{
u8 *b_eeprom = (u8 *)eeprom;
u8 addr;
* @eeprom: caller allocated strcuture to read the eeprom data into
* @io_port: io port to read from
**/
-static void __init check_eeprom(struct NvRamType *eeprom, u16 io_port)
+static void __devinit check_eeprom(struct NvRamType *eeprom, unsigned long io_port)
{
u16 *w_eeprom = (u16 *)eeprom;
u16 w_addr;
*
* @eeprom: The eeprom data strucutre to show details for.
**/
-static void __init print_eeprom_settings(struct NvRamType *eeprom)
+static void __devinit print_eeprom_settings(struct NvRamType *eeprom)
{
dprintkl(KERN_INFO, "Used settings: AdapterID=%02i, Speed=%i(%02i.%01iMHz), dev_mode=0x%02x\n",
eeprom->scsi_id,
const unsigned srbs_per_page = PAGE_SIZE/SEGMENTX_LEN;
for (i = 0; i < DC395x_MAX_SRB_CNT; i += srbs_per_page)
- if (acb->srb_array[i].segment_x)
- kfree(acb->srb_array[i].segment_x);
+ kfree(acb->srb_array[i].segment_x);
}
/*
* Allocate SG tables; as we have to pci_map them, an SG list (struct SGentry*)
* should never cross a page boundary */
-static int __init adapter_sg_tables_alloc(struct AdapterCtlBlk *acb)
+static int __devinit adapter_sg_tables_alloc(struct AdapterCtlBlk *acb)
{
const unsigned mem_needed = (DC395x_MAX_SRB_CNT+1)
*SEGMENTX_LEN;
dprintkdbg(DBG_1, "Allocate %i pages for SG tables\n", pages);
while (pages--) {
- ptr = (struct SGentry *)kmalloc(PAGE_SIZE, GFP_KERNEL);
+ ptr = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!ptr) {
adapter_sg_tables_free(acb);
return 1;
*
* @acb: The adapter to print the information for.
**/
-static void __init adapter_print_config(struct AdapterCtlBlk *acb)
+static void __devinit adapter_print_config(struct AdapterCtlBlk *acb)
{
u8 bval;
*
* @acb: The adapter to initialize.
**/
-static void __init adapter_init_params(struct AdapterCtlBlk *acb)
+static void __devinit adapter_init_params(struct AdapterCtlBlk *acb)
{
struct NvRamType *eeprom = &acb->eeprom;
int i;
*
* @host: The scsi host instance to fill in the values for.
**/
-static void __init adapter_init_scsi_host(struct Scsi_Host *host)
+static void __devinit adapter_init_scsi_host(struct Scsi_Host *host)
{
struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)host->hostdata;
struct NvRamType *eeprom = &acb->eeprom;
*
* @acb: The adapter which we are to init.
**/
-void __init adapter_init_chip(struct AdapterCtlBlk *acb)
+static void __devinit adapter_init_chip(struct AdapterCtlBlk *acb)
{
struct NvRamType *eeprom = &acb->eeprom;
* Returns 0 if the initialization succeeds, any other value on
* failure.
**/
-static int __init adapter_init(struct AdapterCtlBlk *acb, u32 io_port,
- u32 io_port_len, u8 irq)
+static int __devinit adapter_init(struct AdapterCtlBlk *acb,
+ unsigned long io_port, u32 io_port_len, unsigned int irq)
{
if (!request_region(io_port, io_port_len, DC395X_NAME)) {
- dprintkl(KERN_ERR, "Failed to reserve IO region 0x%x\n", io_port);
+ dprintkl(KERN_ERR, "Failed to reserve IO region 0x%lx\n", io_port);
goto failed;
}
/* store port base to indicate we have registered it */
acb->io_port_base = io_port;
acb->io_port_len = io_port_len;
- if (request_irq(irq, dc395x_interrupt, SA_SHIRQ, DC395X_NAME, acb)) {
+ if (request_irq(irq, dc395x_interrupt, IRQF_SHARED, DC395X_NAME, acb)) {
/* release the region we just claimed */
dprintkl(KERN_INFO, "Failed to register IRQ\n");
goto failed;
acb->irq_level = irq;
/* get eeprom configuration information and command line settings etc */
- check_eeprom(&acb->eeprom, (u16)io_port);
+ check_eeprom(&acb->eeprom, io_port);
print_eeprom_settings(&acb->eeprom);
/* setup adapter control block */
SPRINTF("SCSI Host Nr %i, ", host->host_no);
SPRINTF("DC395U/UW/F DC315/U %s\n",
(acb->config & HCC_WIDE_CARD) ? "Wide" : "");
- SPRINTF("io_port_base 0x%04x, ", acb->io_port_base);
- SPRINTF("irq_level 0x%02x, ", acb->irq_level);
+ SPRINTF("io_port_base 0x%04lx, ", acb->io_port_base);
+ SPRINTF("irq_level 0x%04x, ", acb->irq_level);
SPRINTF(" SelTimeout %ims\n", (1638 * acb->sel_timeout) / 1000);
SPRINTF("MaxID %i, MaxLUN %i, ", host->max_id, host->max_lun);
}
-static Scsi_Host_Template dc395x_driver_template = {
+static struct scsi_host_template dc395x_driver_template = {
.module = THIS_MODULE,
.proc_name = DC395X_NAME,
.proc_info = dc395x_proc_info,
static int __devinit dc395x_init_one(struct pci_dev *dev,
const struct pci_device_id *id)
{
- struct Scsi_Host *scsi_host;
- struct AdapterCtlBlk *acb;
- unsigned int io_port_base;
+ struct Scsi_Host *scsi_host = NULL;
+ struct AdapterCtlBlk *acb = NULL;
+ unsigned long io_port_base;
unsigned int io_port_len;
- u8 irq;
+ unsigned int irq;
dprintkdbg(DBG_0, "Init one instance (%s)\n", pci_name(dev));
banner_display();
io_port_base = pci_resource_start(dev, 0) & PCI_BASE_ADDRESS_IO_MASK;
io_port_len = pci_resource_len(dev, 0);
irq = dev->irq;
- dprintkdbg(DBG_0, "IO_PORT=%04x, IRQ=%x\n", io_port_base, dev->irq);
+ dprintkdbg(DBG_0, "IO_PORT=0x%04lx, IRQ=0x%x\n", io_port_base, dev->irq);
/* allocate scsi host information (includes out adapter) */
scsi_host = scsi_host_alloc(&dc395x_driver_template,
sizeof(struct AdapterCtlBlk));
if (!scsi_host) {
dprintkl(KERN_INFO, "scsi_host_alloc failed\n");
- return -ENOMEM;
+ goto fail;
}
acb = (struct AdapterCtlBlk*)scsi_host->hostdata;
acb->scsi_host = scsi_host;
+ acb->dev = dev;
/* initialise the adapter and everything we need */
if (adapter_init(acb, io_port_base, io_port_len, irq)) {
dprintkl(KERN_INFO, "adapter init failed\n");
- scsi_host_put(scsi_host);
- return -ENODEV;
+ goto fail;
}
pci_set_master(dev);
/* get the scsi mid level to scan for new devices on the bus */
if (scsi_add_host(scsi_host, &dev->dev)) {
dprintkl(KERN_ERR, "scsi_add_host failed\n");
- adapter_uninit(acb);
- scsi_host_put(scsi_host);
- return -ENODEV;
+ goto fail;
}
pci_set_drvdata(dev, scsi_host);
scsi_scan_host(scsi_host);
return 0;
+
+fail:
+ if (acb != NULL)
+ adapter_uninit(acb);
+ if (scsi_host != NULL)
+ scsi_host_put(scsi_host);
+ pci_disable_device(dev);
+ return -ENODEV;
}
scsi_remove_host(scsi_host);
adapter_uninit(acb);
+ pci_disable_device(dev);
scsi_host_put(scsi_host);
pci_set_drvdata(dev, NULL);
}
**/
static int __init dc395x_module_init(void)
{
- return pci_module_init(&dc395x_driver);
+ return pci_register_driver(&dc395x_driver);
}