#include <linux/spinlock.h>
#include <linux/pci.h>
#include <linux/list.h>
+#include <linux/vmalloc.h>
#include <asm/io.h>
#include <scsi/scsi.h>
* cross a page boundy.
*/
#define SEGMENTX_LEN (sizeof(struct SGentry)*DC395x_MAX_SG_LISTENTRY)
-
+#define VIRTX_LEN (sizeof(void *) * DC395x_MAX_SG_LISTENTRY)
struct SGentry {
u32 address; /* bus! address */
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 */
+ void **virt_map;
unsigned char *virt_addr; /* Virtual address of current transfer position */
/*
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;
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;
- sgp[i].address = busaddr;
+ u32 seglen = (u32)sg_dma_len(sl + i);
+ sgp[i].address = (u32)sg_dma_address(sl + i);
sgp[i].length = seglen;
srb->total_xfer_length += seglen;
+ srb->virt_map[i] = kmap(sl[i].page);
}
+ srb->virt_addr = srb->virt_map[0];
sgp += srb->sg_count - 1;
/*
int segment = cmd->use_sg;
u32 xferred = srb->total_xfer_length - left; /* bytes transfered */
struct SGentry *psge = srb->segment_x + srb->sg_index;
+ void **virt = srb->virt_map;
dprintkdbg(DBG_0,
"sg_update_list: Transfered %i of %i bytes, %i remain\n",
/* We have to walk the scatterlist to find it */
sg = (struct scatterlist *)cmd->request_buffer;
+ idx = 0;
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));
+ srb->virt_addr = virt[idx] + (psge->address & ~PAGE_MASK);
return;
}
++sg;
+ ++idx;
}
dprintkl(KERN_ERR, "sg_update_list: sg_to_virt failed\n");
DC395x_read32(acb, TRM_S1040_DMA_CXCNT));
}
/*
- * calculate all the residue data that not yet tranfered
+ * calculate all the residue data that not yet transfered
* SCSI transfer counter + left in SCSI FIFO data
*
* .....TRM_S1040_SCSI_COUNTER (24bits)
struct scsi_cmnd *cmd = srb->cmd;
enum dma_data_direction dir = cmd->sc_data_direction;
if (cmd->use_sg && dir != PCI_DMA_NONE) {
+ int i;
/* unmap DC395x SG list */
dprintkdbg(DBG_SG, "pci_unmap_srb: list=%08x(%05x)\n",
srb->sg_bus_addr, SEGMENTX_LEN);
dprintkdbg(DBG_SG, "pci_unmap_srb: segs=%i buffer=%p\n",
cmd->use_sg, cmd->request_buffer);
/* unmap the sg segments */
+ for (i = 0; i < srb->sg_count; i++)
+ kunmap(virt_to_page(srb->virt_map[i]));
pci_unmap_sg(acb->dev,
(struct scatterlist *)cmd->request_buffer,
cmd->use_sg, dir);
if (cmd->use_sg) {
struct scatterlist* sg = (struct scatterlist *)cmd->request_buffer;
- ptr = (struct ScsiInqData *)(page_address(sg->page) + sg->offset);
+ ptr = (struct ScsiInqData *)(srb->virt_map[0] + sg->offset);
} else {
ptr = (struct ScsiInqData *)(cmd->request_buffer);
}
*
* @io_port: base I/O address
**/
-static void __init trms1040_wait_30us(unsigned long 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(unsigned long 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(unsigned long 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, unsigned long 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(unsigned long 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, unsigned long 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, unsigned long 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);
+
+ vfree(acb->srb_array[0].virt_map);
}
/*
* 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;
int srb_idx = 0;
unsigned i = 0;
struct SGentry *ptr;
+ void **virt_array;
- for (i = 0; i < DC395x_MAX_SRB_CNT; i++)
+ for (i = 0; i < DC395x_MAX_SRB_CNT; i++) {
acb->srb_array[i].segment_x = NULL;
+ acb->srb_array[i].virt_map = NULL;
+ }
dprintkdbg(DBG_1, "Allocate %i pages for SG tables\n", pages);
while (pages--) {
ptr + (i * DC395x_MAX_SG_LISTENTRY);
else
dprintkl(KERN_DEBUG, "No space for tmsrb SG table reserved?!\n");
+
+ virt_array = vmalloc((DC395x_MAX_SRB_CNT + 1) * DC395x_MAX_SG_LISTENTRY * sizeof(void*));
+
+ if (!virt_array) {
+ adapter_sg_tables_free(acb);
+ return 1;
+ }
+
+ for (i = 0; i < DC395x_MAX_SRB_CNT + 1; i++) {
+ acb->srb_array[i].virt_map = virt_array;
+ virt_array += DC395x_MAX_SG_LISTENTRY;
+ }
+
return 0;
}
*
* @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.
**/
-static 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,
+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)) {