#include <sys/thread2.h>
#define MLY_MAX_COMMANDS 256
#define MLY_MAX_SGENTRIES 64
#define MLY_PERIODIC_INTERVAL 1
# include <sys/taskqueue.h>
#ifndef INTR_ENTROPY
# define INTR_ENTROPY 0
#endif
#ifdef MLY_DEBUG
# define debug(level, fmt, args...) do { if (level <= MLY_DEBUG) kprintf("%s: " fmt "\n", __func__ , ##args); } while(0)
# define debug_called(level) do { if (level <= MLY_DEBUG) kprintf("%s: called\n", __func__); } while(0)
# define debug_struct(s) kprintf(" SIZE %s: %d\n", #s, sizeof(struct s))
# define debug_union(s) kprintf(" SIZE %s: %d\n", #s, sizeof(union s))
# define debug_field(s, f) kprintf(" OFFSET %s.%s: %d\n", #s, #f, ((int)&(((struct s *)0)->f)))
extern void mly_printstate0(void);
extern struct mly_softc *mly_softc0;
#else
# define debug(level, fmt, args...)
# define debug_called(level)
# define debug_struct(s)
#endif
#define mly_printf(sc, fmt, args...) device_printf(sc->mly_dev, fmt , ##args)
struct mly_btl {
int mb_flags;
#define MLY_BTL_PHYSICAL (1<<0)
#define MLY_BTL_LOGICAL (1<<1)
#define MLY_BTL_PROTECTED (1<<2)
#define MLY_BTL_RESCAN (1<<3)
char mb_name[16];
int mb_state;
int mb_type;
int mb_speed;
int mb_width;
};
struct mly_command {
TAILQ_ENTRY(mly_command) mc_link;
struct mly_softc *mc_sc;
u_int16_t mc_slot;
int mc_flags;
#define MLY_CMD_BUSY (1<<0)
#define MLY_CMD_COMPLETE (1<<1)
#define MLY_CMD_MAPPED (1<<3)
#define MLY_CMD_DATAIN (1<<4)
#define MLY_CMD_DATAOUT (1<<5)
u_int16_t mc_status;
u_int8_t mc_sense;
int32_t mc_resid;
union mly_command_packet *mc_packet;
u_int64_t mc_packetphys;
void *mc_data;
size_t mc_length;
bus_dmamap_t mc_datamap;
void (* mc_complete)(struct mly_command *mc);
void *mc_private;
int mc_timestamp;
};
#define MLY_SLOT_START 1
#define MLY_SLOT_MAX (MLY_SLOT_START + MLY_MAX_COMMANDS)
struct mly_softc {
device_t mly_dev;
cdev_t mly_dev_t;
struct resource *mly_regs_resource;
int mly_regs_rid;
bus_space_handle_t mly_bhandle;
bus_space_tag_t mly_btag;
bus_dma_tag_t mly_parent_dmat;
bus_dma_tag_t mly_buffer_dmat;
struct resource *mly_irq;
int mly_irq_rid;
void *mly_intr;
struct mly_sg_entry *mly_sg_table;
u_int32_t mly_sg_busaddr;
bus_dma_tag_t mly_sg_dmat;
bus_dmamap_t mly_sg_dmamap;
int mly_hwif;
#define MLY_HWIF_I960RX 0
#define MLY_HWIF_STRONGARM 1
u_int8_t mly_doorbell_true;
u_int8_t mly_command_mailbox;
u_int8_t mly_status_mailbox;
u_int8_t mly_idbr;
u_int8_t mly_odbr;
u_int8_t mly_error_status;
u_int8_t mly_interrupt_status;
u_int8_t mly_interrupt_mask;
struct mly_mmbox *mly_mmbox;
u_int64_t mly_mmbox_busaddr;
bus_dma_tag_t mly_mmbox_dmat;
bus_dmamap_t mly_mmbox_dmamap;
u_int32_t mly_mmbox_command_index;
u_int32_t mly_mmbox_status_index;
int mly_state;
#define MLY_STATE_OPEN (1<<1)
#define MLY_STATE_INTERRUPTS_ON (1<<2)
#define MLY_STATE_MMBOX_ACTIVE (1<<3)
#define MLY_STATE_CAM_FROZEN (1<<4)
struct mly_ioctl_getcontrollerinfo *mly_controllerinfo;
struct mly_param_controller *mly_controllerparam;
struct mly_btl mly_btl[MLY_MAX_CHANNELS][MLY_MAX_TARGETS];
struct mly_command mly_command[MLY_MAX_COMMANDS];
union mly_command_packet *mly_packet;
bus_dma_tag_t mly_packet_dmat;
bus_dmamap_t mly_packetmap;
u_int64_t mly_packetphys;
TAILQ_HEAD(,mly_command) mly_free;
TAILQ_HEAD(,mly_command) mly_busy;
TAILQ_HEAD(,mly_command) mly_complete;
struct mly_qstat mly_qstat[MLYQ_COUNT];
u_int32_t mly_event_change;
u_int32_t mly_event_counter;
u_int32_t mly_event_waiting;
struct callout mly_periodic;
struct callout mly_timeout;
struct cam_devq *mly_cam_devq;
struct cam_sim *mly_cam_sim[MLY_MAX_CHANNELS];
int mly_cam_channels;
struct task mly_task_complete;
int mly_qfrzn_cnt;
};
#define MLY_SET_REG(sc, reg, val) bus_space_write_1(sc->mly_btag, sc->mly_bhandle, reg, val)
#define MLY_GET_REG(sc, reg) bus_space_read_1 (sc->mly_btag, sc->mly_bhandle, reg)
#define MLY_GET_REG2(sc, reg) bus_space_read_2 (sc->mly_btag, sc->mly_bhandle, reg)
#define MLY_GET_REG4(sc, reg) bus_space_read_4 (sc->mly_btag, sc->mly_bhandle, reg)
#define MLY_SET_MBOX(sc, mbox, ptr) \
do { \
bus_space_write_4(sc->mly_btag, sc->mly_bhandle, mbox, *((u_int32_t *)ptr)); \
bus_space_write_4(sc->mly_btag, sc->mly_bhandle, mbox + 4, *((u_int32_t *)ptr + 1)); \
bus_space_write_4(sc->mly_btag, sc->mly_bhandle, mbox + 8, *((u_int32_t *)ptr + 2)); \
bus_space_write_4(sc->mly_btag, sc->mly_bhandle, mbox + 12, *((u_int32_t *)ptr + 3)); \
} while(0);
#define MLY_GET_MBOX(sc, mbox, ptr) \
do { \
*((u_int32_t *)ptr) = bus_space_read_4(sc->mly_btag, sc->mly_bhandle, mbox); \
*((u_int32_t *)ptr + 1) = bus_space_read_4(sc->mly_btag, sc->mly_bhandle, mbox + 4); \
*((u_int32_t *)ptr + 2) = bus_space_read_4(sc->mly_btag, sc->mly_bhandle, mbox + 8); \
*((u_int32_t *)ptr + 3) = bus_space_read_4(sc->mly_btag, sc->mly_bhandle, mbox + 12); \
} while(0);
#define MLY_IDBR_TRUE(sc, mask) \
((((MLY_GET_REG((sc), (sc)->mly_idbr)) ^ (sc)->mly_doorbell_true) & (mask)) == (mask))
#define MLY_ODBR_TRUE(sc, mask) \
((MLY_GET_REG((sc), (sc)->mly_odbr) & (mask)) == (mask))
#define MLY_ERROR_VALID(sc) \
((((MLY_GET_REG((sc), (sc)->mly_error_status)) ^ (sc)->mly_doorbell_true) & (MLY_MSG_EMPTY)) == 0)
#define MLY_MASK_INTERRUPTS(sc) \
do { \
MLY_SET_REG((sc), (sc)->mly_interrupt_mask, MLY_INTERRUPT_MASK_DISABLE); \
sc->mly_state &= ~MLY_STATE_INTERRUPTS_ON; \
} while(0);
#define MLY_UNMASK_INTERRUPTS(sc) \
do { \
MLY_SET_REG((sc), (sc)->mly_interrupt_mask, MLY_INTERRUPT_MASK_ENABLE); \
sc->mly_state |= MLY_STATE_INTERRUPTS_ON; \
} while(0);
#define MLY_LOGDEV_ID(sc, bus, target) (((bus) - (sc)->mly_controllerinfo->physical_channels_present) * \
MLY_MAX_TARGETS + (target))
#define MLY_LOGDEV_BUS(sc, logdev) (((logdev) / MLY_MAX_TARGETS) + \
(sc)->mly_controllerinfo->physical_channels_present)
#define MLY_LOGDEV_TARGET(sc, logdev) ((logdev) % MLY_MAX_TARGETS)
#define MLY_BUS_IS_VIRTUAL(sc, bus) ((bus) >= (sc)->mly_controllerinfo->physical_channels_present)
#define MLY_BUS_IS_VALID(sc, bus) (((bus) < (sc)->mly_cam_channels) && ((sc)->mly_cam_sim[(bus)] != NULL))
#define MLYQ_ADD(sc, qname) \
do { \
struct mly_qstat *qs = &(sc)->mly_qstat[qname]; \
\
qs->q_length++; \
if (qs->q_length > qs->q_max) \
qs->q_max = qs->q_length; \
} while(0)
#define MLYQ_REMOVE(sc, qname) (sc)->mly_qstat[qname].q_length--
#define MLYQ_INIT(sc, qname) \
do { \
sc->mly_qstat[qname].q_length = 0; \
sc->mly_qstat[qname].q_max = 0; \
} while(0)
#define MLYQ_COMMAND_QUEUE(name, index) \
static __inline void \
mly_initq_ ## name (struct mly_softc *sc) \
{ \
TAILQ_INIT(&sc->mly_ ## name); \
MLYQ_INIT(sc, index); \
} \
static __inline void \
mly_enqueue_ ## name (struct mly_command *mc) \
{ \
crit_enter(); \
TAILQ_INSERT_TAIL(&mc->mc_sc->mly_ ## name, mc, mc_link); \
MLYQ_ADD(mc->mc_sc, index); \
crit_exit(); \
} \
static __inline void \
mly_requeue_ ## name (struct mly_command *mc) \
{ \
crit_enter(); \
TAILQ_INSERT_HEAD(&mc->mc_sc->mly_ ## name, mc, mc_link); \
MLYQ_ADD(mc->mc_sc, index); \
crit_exit(); \
} \
static __inline struct mly_command * \
mly_dequeue_ ## name (struct mly_softc *sc) \
{ \
struct mly_command *mc; \
\
crit_enter(); \
if ((mc = TAILQ_FIRST(&sc->mly_ ## name)) != NULL) { \
TAILQ_REMOVE(&sc->mly_ ## name, mc, mc_link); \
MLYQ_REMOVE(sc, index); \
} \
crit_exit(); \
return(mc); \
} \
static __inline void \
mly_remove_ ## name (struct mly_command *mc) \
{ \
crit_enter(); \
TAILQ_REMOVE(&mc->mc_sc->mly_ ## name, mc, mc_link); \
MLYQ_REMOVE(mc->mc_sc, index); \
crit_exit(); \
} \
struct hack
MLYQ_COMMAND_QUEUE(free, MLYQ_FREE);
MLYQ_COMMAND_QUEUE(busy, MLYQ_BUSY);
MLYQ_COMMAND_QUEUE(complete, MLYQ_COMPLETE);
static __inline void
padstr(char *targ, char *src, int len)
{
while (len-- > 0) {
if (*src != 0) {
*targ++ = *src++;
} else {
*targ++ = ' ';
}
}
}