*
*-----------------------------------------------------------------------------
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
*
- * Where this Software is combined with software released under the terms of
- * the GNU Public License ("GPL") and the terms of the GPL would require the
- * combined work to also be released under the terms of the GPL, the terms
- * and conditions of this License will apply in addition to those of the
- * GPL with the exception of any terms or conditions of this License that
- * conflict with, or are expressly prohibited by, the GPL.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <linux/gfp.h>
+
#ifndef SYM_HIPD_H
#define SYM_HIPD_H
* They may be defined in platform specific headers, if they
* are useful.
*
- * SYM_OPT_HANDLE_DIR_UNKNOWN
- * When this option is set, the SCRIPTS used by the driver
- * are able to handle SCSI transfers with direction not
- * supplied by user.
- * (set for Linux-2.0.X)
- *
* SYM_OPT_HANDLE_DEVICE_QUEUEING
* When this option is set, the driver will use a queue per
* device and handle QUEUE FULL status requeuing internally.
*
- * SYM_OPT_SNIFF_INQUIRY
- * When this option is set, the driver sniff out successful
- * INQUIRY response and performs negotiations accordingly.
- * (set for Linux)
- *
* SYM_OPT_LIMIT_COMMAND_REORDERING
* When this option is set, the driver tries to limit tagged
* command reordering to some reasonnable value.
* (set for Linux)
*/
#if 0
-#define SYM_OPT_HANDLE_DIR_UNKNOWN
#define SYM_OPT_HANDLE_DEVICE_QUEUEING
-#define SYM_OPT_SNIFF_INQUIRY
#define SYM_OPT_LIMIT_COMMAND_REORDERING
#endif
*/
#define SYM_CONF_MIN_ASYNC (40)
+
+/*
+ * MEMORY ALLOCATOR.
+ */
+
+#define SYM_MEM_WARN 1 /* Warn on failed operations */
+
+#define SYM_MEM_PAGE_ORDER 0 /* 1 PAGE maximum */
+#define SYM_MEM_CLUSTER_SHIFT (PAGE_SHIFT+SYM_MEM_PAGE_ORDER)
+#define SYM_MEM_FREE_UNUSED /* Free unused pages immediately */
/*
* Shortest memory chunk is (1<<SYM_MEM_SHIFT), currently 16.
* Actual allocations happen as SYM_MEM_CLUSTER_SIZE sized.
/*
* Common definitions for both bus space based and legacy IO methods.
*/
-#define INB(r) INB_OFF(offsetof(struct sym_reg,r))
-#define INW(r) INW_OFF(offsetof(struct sym_reg,r))
-#define INL(r) INL_OFF(offsetof(struct sym_reg,r))
-#define OUTB(r, v) OUTB_OFF(offsetof(struct sym_reg,r), (v))
-#define OUTW(r, v) OUTW_OFF(offsetof(struct sym_reg,r), (v))
-#define OUTL(r, v) OUTL_OFF(offsetof(struct sym_reg,r), (v))
+#define INB_OFF(np, o) ioread8(np->s.ioaddr + (o))
+#define INW_OFF(np, o) ioread16(np->s.ioaddr + (o))
+#define INL_OFF(np, o) ioread32(np->s.ioaddr + (o))
+
+#define OUTB_OFF(np, o, val) iowrite8((val), np->s.ioaddr + (o))
+#define OUTW_OFF(np, o, val) iowrite16((val), np->s.ioaddr + (o))
+#define OUTL_OFF(np, o, val) iowrite32((val), np->s.ioaddr + (o))
+
+#define INB(np, r) INB_OFF(np, offsetof(struct sym_reg, r))
+#define INW(np, r) INW_OFF(np, offsetof(struct sym_reg, r))
+#define INL(np, r) INL_OFF(np, offsetof(struct sym_reg, r))
+
+#define OUTB(np, r, v) OUTB_OFF(np, offsetof(struct sym_reg, r), (v))
+#define OUTW(np, r, v) OUTW_OFF(np, offsetof(struct sym_reg, r), (v))
+#define OUTL(np, r, v) OUTL_OFF(np, offsetof(struct sym_reg, r), (v))
-#define OUTONB(r, m) OUTB(r, INB(r) | (m))
-#define OUTOFFB(r, m) OUTB(r, INB(r) & ~(m))
-#define OUTONW(r, m) OUTW(r, INW(r) | (m))
-#define OUTOFFW(r, m) OUTW(r, INW(r) & ~(m))
-#define OUTONL(r, m) OUTL(r, INL(r) | (m))
-#define OUTOFFL(r, m) OUTL(r, INL(r) & ~(m))
+#define OUTONB(np, r, m) OUTB(np, r, INB(np, r) | (m))
+#define OUTOFFB(np, r, m) OUTB(np, r, INB(np, r) & ~(m))
+#define OUTONW(np, r, m) OUTW(np, r, INW(np, r) | (m))
+#define OUTOFFW(np, r, m) OUTW(np, r, INW(np, r) & ~(m))
+#define OUTONL(np, r, m) OUTL(np, r, INL(np, r) | (m))
+#define OUTOFFL(np, r, m) OUTL(np, r, INL(np, r) & ~(m))
/*
* We normally want the chip to have a consistent view
* of driver internal data structures when we restart it.
* Thus these macros.
*/
-#define OUTL_DSP(v) \
+#define OUTL_DSP(np, v) \
do { \
MEMORY_WRITE_BARRIER(); \
- OUTL (nc_dsp, (v)); \
+ OUTL(np, nc_dsp, (v)); \
} while (0)
#define OUTONB_STD() \
do { \
MEMORY_WRITE_BARRIER(); \
- OUTONB (nc_dcntl, (STD|NOCOM)); \
+ OUTONB(np, nc_dcntl, (STD|NOCOM)); \
} while (0)
/*
* Host adapter miscellaneous flags.
*/
#define SYM_AVOID_BUS_RESET (1)
-#define SYM_SCAN_TARGETS_HILO (1<<1)
/*
* Misc.
* Gather negotiable parameters value
*/
struct sym_trans {
- u8 scsi_version;
- u8 spi_version;
u8 period;
u8 offset;
- u8 width;
- u8 options; /* PPR options */
-};
-
-struct sym_tinfo {
- struct sym_trans curr;
- struct sym_trans goal;
- struct sym_trans user;
-#ifdef SYM_OPT_ANNOUNCE_TRANSFER_RATE
- struct sym_trans prev;
-#endif
+ unsigned int width:1;
+ unsigned int iu:1;
+ unsigned int dt:1;
+ unsigned int qas:1;
+ unsigned int check_nego:1;
};
/*
/*
* LUN table used by the C code.
*/
- lcb_p lun0p; /* LCB of LUN #0 (usual case) */
+ struct sym_lcb *lun0p; /* LCB of LUN #0 (usual case) */
#if SYM_CONF_MAX_LUN > 1
- lcb_p *lunmp; /* Other LCBs [1..MAX_LUN] */
+ struct sym_lcb **lunmp; /* Other LCBs [1..MAX_LUN] */
#endif
- /*
- * Bitmap that tells about LUNs that succeeded at least
- * 1 IO and therefore assumed to be a real device.
- * Avoid useless allocation of the LCB structure.
- */
- u32 lun_map[(SYM_CONF_MAX_LUN+31)/32];
-
- /*
- * Bitmap that tells about LUNs that haven't yet an LCB
- * allocated (not discovered or LCB allocation failed).
- */
- u32 busy0_map[(SYM_CONF_MAX_LUN+31)/32];
-
#ifdef SYM_HAVE_STCB
/*
* O/S specific data structure.
struct sym_stcb s;
#endif
- /*
- * Transfer capabilities (SIP)
- */
- struct sym_tinfo tinfo;
+ /* Transfer goal */
+ struct sym_trans tgoal;
/*
* Keep track of the CCB used for the negotiation in order
* to ensure that only 1 negotiation is queued at a time.
*/
- ccb_p nego_cp; /* CCB used for the nego */
+ struct sym_ccb * nego_cp; /* CCB used for the nego */
/*
* Set when we want to reset the device.
* Other user settable limits and options.
* These limits are read from the NVRAM if present.
*/
- u_char usrflags;
- u_short usrtags;
-
-#ifdef SYM_OPT_SNIFF_INQUIRY
- /*
- * Some minimal information from INQUIRY response.
- */
- u32 cmdq_map[(SYM_CONF_MAX_LUN+31)/32];
- u_char inq_version;
- u_char inq_byte7;
- u_char inq_byte56;
- u_char inq_byte7_valid;
-#endif
-
+ unsigned char usrflags;
+ unsigned char usr_period;
+ unsigned char usr_width;
+ unsigned short usrtags;
+ struct scsi_target *starget;
};
/*
* Optionnaly the driver can handle device queueing,
* and requeues internally command to redo.
*/
- SYM_QUEHEAD
- waiting_ccbq;
- SYM_QUEHEAD
- started_ccbq;
+ SYM_QUEHEAD waiting_ccbq;
+ SYM_QUEHEAD started_ccbq;
int num_sgood;
u_short started_tags;
u_short started_no_tag;
#ifdef SYM_OPT_LIMIT_COMMAND_REORDERING
/*
- * Optionnaly the driver can try to prevent SCSI
- * IOs from being too much reordering.
+ * Optionally the driver can try to prevent SCSI
+ * IOs from being reordered too much.
*/
u_char tags_si; /* Current index to tags sum */
u_short tags_sum[2]; /* Tags sum counters */
* LUN(s) > 0.
*/
#if SYM_CONF_MAX_LUN <= 1
-#define sym_lp(np, tp, lun) (!lun) ? (tp)->lun0p : NULL
+#define sym_lp(tp, lun) (!lun) ? (tp)->lun0p : NULL
#else
-#define sym_lp(np, tp, lun) \
+#define sym_lp(tp, lun) \
(!lun) ? (tp)->lun0p : (tp)->lunmp ? (tp)->lunmp[(lun)] : NULL
#endif
*/
u32 savep; /* Jump address to saved data pointer */
u32 lastp; /* SCRIPTS address at end of data */
-#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
- u32 wlastp;
-#endif
/*
* Status fields.
/*
* Pointer to CAM ccb and related stuff.
*/
- cam_ccb_p cam_ccb; /* CAM scsiio ccb */
+ struct scsi_cmnd *cmd; /* CAM scsiio ccb */
u8 cdb_buf[16]; /* Copy of CDB */
- u8 *sns_bbuf; /* Bounce buffer for sense data */
-#ifndef SYM_SNS_BBUF_LEN
-#define SYM_SNS_BBUF_LEN (32)
-#endif
+#define SYM_SNS_BBUF_LEN 32
+ u8 sns_bbuf[SYM_SNS_BBUF_LEN]; /* Bounce buffer for sense data */
int data_len; /* Total data length */
int segments; /* Number of SG segments */
u8 order; /* Tag type (if tagged command) */
+ unsigned char odd_byte_adjustment; /* odd-sized req on wide bus */
- /*
- * Miscellaneous status'.
- */
u_char nego_status; /* Negotiation status */
u_char xerr_status; /* Extended error flags */
u32 extra_bytes; /* Extraneous bytes transferred */
u_char sv_xerr_status; /* Saved extended status */
int sv_resid; /* Saved residual */
- /*
- * O/S specific data structure.
- */
-#ifdef SYM_HAVE_SCCB
- struct sym_sccb s;
-#endif
/*
* Other fields.
*/
-#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
- SYM_QUEHEAD tmo_linkq; /* Optional timeout handling */
- u_int tmo_clock; /* (link and dealine value) */
-#endif
u32 ccb_ba; /* BUS address of this CCB */
u_short tag; /* Tag for this transfer */
/* NO_TAG means no tag */
u_char target;
u_char lun;
- ccb_p link_ccbh; /* Host adapter CCB hash chain */
- SYM_QUEHEAD
- link_ccbq; /* Link to free/busy CCB queue */
+ struct sym_ccb *link_ccbh; /* Host adapter CCB hash chain */
+ SYM_QUEHEAD link_ccbq; /* Link to free/busy CCB queue */
u32 startp; /* Initial data pointer */
u32 goalp; /* Expected last data pointer */
-#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
- u32 wgoalp;
-#endif
int ext_sg; /* Extreme data pointer, used */
int ext_ofs; /* to calculate the residual. */
#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
- SYM_QUEHEAD
- link2_ccbq; /* Link for device queueing */
+ SYM_QUEHEAD link2_ccbq; /* Link for device queueing */
u_char started; /* CCB queued to the squeue */
#endif
u_char to_abort; /* Want this IO to be aborted */
#endif
};
-#define CCB_BA(cp,lbl) (cp->ccb_ba + offsetof(struct sym_ccb, lbl))
+#define CCB_BA(cp,lbl) cpu_to_scr(cp->ccb_ba + offsetof(struct sym_ccb, lbl))
-#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
-#define sym_goalp(cp) ((cp->host_flags & HF_DATA_IN) ? cp->goalp : cp->wgoalp)
-#else
-#define sym_goalp(cp) (cp->goalp)
-#endif
+typedef struct device *m_pool_ident_t;
/*
* Host Control Block
struct sym_fwa_ba fwa_bas; /* Useful SCRIPTA bus addresses */
struct sym_fwb_ba fwb_bas; /* Useful SCRIPTB bus addresses */
struct sym_fwz_ba fwz_bas; /* Useful SCRIPTZ bus addresses */
- void (*fw_setup)(hcb_p np, struct sym_fw *fw);
- void (*fw_patch)(hcb_p np);
+ void (*fw_setup)(struct sym_hcb *np, struct sym_fw *fw);
+ void (*fw_patch)(struct sym_hcb *np);
char *fw_name;
/*
/*
* CCB lists and queue.
*/
- ccb_p *ccbh; /* CCBs hashed by DSA value */
+ struct sym_ccb **ccbh; /* CCBs hashed by DSA value */
/* CCB_HASH_SIZE lists of CCBs */
SYM_QUEHEAD free_ccbq; /* Queue of available CCBs */
SYM_QUEHEAD busy_ccbq; /* Queue of busy CCBs */
#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
SYM_QUEHEAD dummy_ccbq;
#endif
- /*
- * Optional handling of IO timeouts.
- */
-#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
- SYM_QUEHEAD tmo0_ccbq;
- SYM_QUEHEAD *tmo_ccbq; /* [2*SYM_TIMEOUT_ORDER_MAX] */
- u_int tmo_clock;
- u_int tmo_actq;
-#endif
/*
* IMMEDIATE ARBITRATION (IARB) control.
#ifdef SYM_CONF_IARB_SUPPORT
u_short iarb_max; /* Max. # consecutive IARB hints*/
u_short iarb_count; /* Actual # of these hints */
- ccb_p last_cp;
+ struct sym_ccb * last_cp;
#endif
/*
/*
* FIRMWARES (sym_fw.c)
*/
-struct sym_fw * sym_find_firmware(struct sym_pci_chip *chip);
-void sym_fw_bind_script (hcb_p np, u32 *start, int len);
+struct sym_fw * sym_find_firmware(struct sym_chip *chip);
+void sym_fw_bind_script(struct sym_hcb *np, u32 *start, int len);
/*
* Driver methods called from O/S specific code.
*/
char *sym_driver_name(void);
-void sym_print_xerr(ccb_p cp, int x_status);
-int sym_reset_scsi_bus(hcb_p np, int enab_int);
-struct sym_pci_chip *
-sym_lookup_pci_chip_table (u_short device_id, u_char revision);
-void sym_put_start_queue(hcb_p np, ccb_p cp);
+void sym_print_xerr(struct scsi_cmnd *cmd, int x_status);
+int sym_reset_scsi_bus(struct sym_hcb *np, int enab_int);
+struct sym_chip *sym_lookup_chip_table(u_short device_id, u_char revision);
#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
-void sym_start_next_ccbs(hcb_p np, lcb_p lp, int maxn);
-#endif
-void sym_start_up (hcb_p np, int reason);
-void sym_interrupt (hcb_p np);
-void sym_flush_comp_queue(hcb_p np, int cam_status);
-int sym_clear_tasks(hcb_p np, int cam_status, int target, int lun, int task);
-ccb_p sym_get_ccb (hcb_p np, u_char tn, u_char ln, u_char tag_order);
-void sym_free_ccb (hcb_p np, ccb_p cp);
-lcb_p sym_alloc_lcb (hcb_p np, u_char tn, u_char ln);
-int sym_queue_scsiio(hcb_p np, cam_scsiio_p csio, ccb_p cp);
-int sym_abort_scsiio(hcb_p np, cam_ccb_p ccb, int timed_out);
-int sym_abort_ccb(hcb_p np, ccb_p cp, int timed_out);
-int sym_reset_scsi_target(hcb_p np, int target);
-void sym_hcb_free(hcb_p np);
-
-#ifdef SYM_OPT_NVRAM_PRE_READ
-int sym_hcb_attach(hcb_p np, struct sym_fw *fw, struct sym_nvram *nvram);
-#else
-int sym_hcb_attach(hcb_p np, struct sym_fw *fw);
+void sym_start_next_ccbs(struct sym_hcb *np, struct sym_lcb *lp, int maxn);
#endif
-
-/*
- * Optionnaly, the driver may handle IO timeouts.
- */
-#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
-int sym_abort_ccb(hcb_p np, ccb_p cp, int timed_out);
-void sym_timeout_ccb(hcb_p np, ccb_p cp, u_int ticks);
-static void __inline sym_untimeout_ccb(hcb_p np, ccb_p cp)
-{
- sym_remque(&cp->tmo_linkq);
- sym_insque_head(&cp->tmo_linkq, &np->tmo0_ccbq);
-}
-void sym_clock(hcb_p np);
-#endif /* SYM_OPT_HANDLE_IO_TIMEOUT */
-
-/*
- * Optionnaly, the driver may provide a function
- * to announce transfer rate changes.
- */
-#ifdef SYM_OPT_ANNOUNCE_TRANSFER_RATE
-void sym_announce_transfer_rate(hcb_p np, int target);
-#endif
-
-/*
- * Optionnaly, the driver may sniff inquiry data.
- */
-#ifdef SYM_OPT_SNIFF_INQUIRY
-#define INQ7_CMDQ (0x02)
-#define INQ7_SYNC (0x10)
-#define INQ7_WIDE16 (0x20)
-
-#define INQ56_CLOCKING (3<<2)
-#define INQ56_ST_ONLY (0<<2)
-#define INQ56_DT_ONLY (1<<2)
-#define INQ56_ST_DT (3<<2)
-
-void sym_update_trans_settings(hcb_p np, tcb_p tp);
-int
-__sym_sniff_inquiry(hcb_p np, u_char tn, u_char ln,
- u_char *inq_data, int inq_len);
-#endif
-
+void sym_start_up(struct sym_hcb *np, int reason);
+void sym_interrupt(struct sym_hcb *np);
+int sym_clear_tasks(struct sym_hcb *np, int cam_status, int target, int lun, int task);
+struct sym_ccb *sym_get_ccb(struct sym_hcb *np, struct scsi_cmnd *cmd, u_char tag_order);
+void sym_free_ccb(struct sym_hcb *np, struct sym_ccb *cp);
+struct sym_lcb *sym_alloc_lcb(struct sym_hcb *np, u_char tn, u_char ln);
+int sym_queue_scsiio(struct sym_hcb *np, struct scsi_cmnd *csio, struct sym_ccb *cp);
+int sym_abort_scsiio(struct sym_hcb *np, struct scsi_cmnd *ccb, int timed_out);
+int sym_reset_scsi_target(struct sym_hcb *np, int target);
+void sym_hcb_free(struct sym_hcb *np);
+int sym_hcb_attach(struct Scsi_Host *shost, struct sym_fw *fw, struct sym_nvram *nvram);
/*
* Build a scatter/gather entry.
(data)->size = cpu_to_scr((((badd) >> 8) & 0xff000000) + len); \
} while (0)
#elif SYM_CONF_DMA_ADDRESSING_MODE == 2
-int sym_lookup_dmap(hcb_p np, u32 h, int s);
+int sym_lookup_dmap(struct sym_hcb *np, u32 h, int s);
static __inline void
-sym_build_sge(hcb_p np, struct sym_tblmove *data, u64 badd, int len)
+sym_build_sge(struct sym_hcb *np, struct sym_tblmove *data, u64 badd, int len)
{
u32 h = (badd>>32);
int s = (h&SYM_DMAP_MASK);
#error "Unsupported DMA addressing mode"
#endif
-/*
- * Set up data pointers used by SCRIPTS.
- * Called from O/S specific code.
- */
-static inline void sym_setup_data_pointers(struct sym_hcb *np,
- struct sym_ccb *cp, int dir)
-{
- u32 lastp, goalp;
-
- /*
- * No segments means no data.
- */
- if (!cp->segments)
- dir = CAM_DIR_NONE;
-
- /*
- * Set the data pointer.
- */
- switch(dir) {
-#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
- case CAM_DIR_UNKNOWN:
-#endif
- case CAM_DIR_OUT:
- goalp = SCRIPTA_BA (np, data_out2) + 8;
- lastp = goalp - 8 - (cp->segments * (2*4));
-#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
- cp->wgoalp = cpu_to_scr(goalp);
- if (dir != CAM_DIR_UNKNOWN)
- break;
- cp->phys.head.wlastp = cpu_to_scr(lastp);
- /* fall through */
-#else
- break;
-#endif
- case CAM_DIR_IN:
- cp->host_flags |= HF_DATA_IN;
- goalp = SCRIPTA_BA (np, data_in2) + 8;
- lastp = goalp - 8 - (cp->segments * (2*4));
- break;
- case CAM_DIR_NONE:
- default:
-#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
- cp->host_flags |= HF_DATA_IN;
-#endif
- lastp = goalp = SCRIPTB_BA (np, no_data);
- break;
- }
-
- /*
- * Set all pointers values needed by SCRIPTS.
- */
- cp->phys.head.lastp = cpu_to_scr(lastp);
- cp->phys.head.savep = cpu_to_scr(lastp);
- cp->startp = cp->phys.head.savep;
- cp->goalp = cpu_to_scr(goalp);
-
-#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
- /*
- * If direction is unknown, start at data_io.
- */
- if (dir == CAM_DIR_UNKNOWN)
- cp->phys.head.savep = cpu_to_scr(SCRIPTB_BA (np, data_io));
-#endif
-}
-
/*
* MEMORY ALLOCATOR.
*/
+#define sym_get_mem_cluster() \
+ (void *) __get_free_pages(GFP_ATOMIC, SYM_MEM_PAGE_ORDER)
+#define sym_free_mem_cluster(p) \
+ free_pages((unsigned long)p, SYM_MEM_PAGE_ORDER)
+
/*
* Link between free memory chunks of a given size.
*/
*/
typedef struct sym_m_vtob { /* Virtual to Bus address translation */
struct sym_m_vtob *next;
-#ifdef SYM_HAVE_M_SVTOB
- struct sym_m_svtob s; /* OS specific data structure */
-#endif
- m_addr_t vaddr; /* Virtual address */
- m_addr_t baddr; /* Bus physical address */
+ void *vaddr; /* Virtual address */
+ dma_addr_t baddr; /* Bus physical address */
} *m_vtob_p;
/* Hash this stuff a bit to speed up translations */
#define VTOB_HASH_SIZE (1UL << VTOB_HASH_SHIFT)
#define VTOB_HASH_MASK (VTOB_HASH_SIZE-1)
#define VTOB_HASH_CODE(m) \
- ((((m_addr_t) (m)) >> SYM_MEM_CLUSTER_SHIFT) & VTOB_HASH_MASK)
+ ((((unsigned long)(m)) >> SYM_MEM_CLUSTER_SHIFT) & VTOB_HASH_MASK)
/*
* Memory pool of a given kind.
*/
typedef struct sym_m_pool {
m_pool_ident_t dev_dmat; /* Identifies the pool (see above) */
- m_addr_t (*get_mem_cluster)(struct sym_m_pool *);
+ void * (*get_mem_cluster)(struct sym_m_pool *);
#ifdef SYM_MEM_FREE_UNUSED
- void (*free_mem_cluster)(struct sym_m_pool *, m_addr_t);
+ void (*free_mem_cluster)(struct sym_m_pool *, void *);
#endif
#define M_GET_MEM_CLUSTER() mp->get_mem_cluster(mp)
#define M_FREE_MEM_CLUSTER(p) mp->free_mem_cluster(mp, p)
-#ifdef SYM_HAVE_M_SPOOL
- struct sym_m_spool s; /* OS specific data structure */
-#endif
int nump;
m_vtob_p vtob[VTOB_HASH_SIZE];
struct sym_m_pool *next;
struct sym_m_link h[SYM_MEM_CLUSTER_SHIFT - SYM_MEM_SHIFT + 1];
} *m_pool_p;
-/*
- * Alloc and free non DMAable memory.
- */
-void sym_mfree_unlocked(void *ptr, int size, char *name);
-void *sym_calloc_unlocked(int size, char *name);
-
/*
* Alloc, free and translate addresses to bus physical
* for DMAable memory.
*/
-void *__sym_calloc_dma_unlocked(m_pool_ident_t dev_dmat, int size, char *name);
-void
-__sym_mfree_dma_unlocked(m_pool_ident_t dev_dmat, void *m,int size, char *name);
-u32 __vtobus_unlocked(m_pool_ident_t dev_dmat, void *m);
+void *__sym_calloc_dma(m_pool_ident_t dev_dmat, int size, char *name);
+void __sym_mfree_dma(m_pool_ident_t dev_dmat, void *m, int size, char *name);
+dma_addr_t __vtobus(m_pool_ident_t dev_dmat, void *m);
/*
* Verbs used by the driver code for DMAable memory handling.
__sym_mfree_dma(np->bus_dmat, _uvptv_(p), l, n)
#define sym_calloc_dma(l, n) _sym_calloc_dma(np, l, n)
#define sym_mfree_dma(p, l, n) _sym_mfree_dma(np, p, l, n)
-#define _vtobus(np, p) __vtobus(np->bus_dmat, _uvptv_(p))
-#define vtobus(p) _vtobus(np, p)
+#define vtobus(p) __vtobus(np->bus_dmat, _uvptv_(p))
/*
- * Override some function names.
+ * We have to provide the driver memory allocator with methods for
+ * it to maintain virtual to bus physical address translations.
*/
-#define PRINT_ADDR sym_print_addr
-#define PRINT_TARGET sym_print_target
-#define PRINT_LUN sym_print_lun
-#define MDELAY sym_mdelay
-#define UDELAY sym_udelay
+
+#define sym_m_pool_match(mp_id1, mp_id2) (mp_id1 == mp_id2)
+
+static __inline void *sym_m_get_dma_mem_cluster(m_pool_p mp, m_vtob_p vbp)
+{
+ void *vaddr = NULL;
+ dma_addr_t baddr = 0;
+
+ vaddr = dma_alloc_coherent(mp->dev_dmat, SYM_MEM_CLUSTER_SIZE, &baddr,
+ GFP_ATOMIC);
+ if (vaddr) {
+ vbp->vaddr = vaddr;
+ vbp->baddr = baddr;
+ }
+ return vaddr;
+}
+
+static __inline void sym_m_free_dma_mem_cluster(m_pool_p mp, m_vtob_p vbp)
+{
+ dma_free_coherent(mp->dev_dmat, SYM_MEM_CLUSTER_SIZE, vbp->vaddr,
+ vbp->baddr);
+}
#endif /* SYM_HIPD_H */