*/
#include "aiclib.c"
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
#include <linux/init.h> /* __setup */
+#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
#include "sd.h" /* For geometry detection */
*/
spinlock_t ahd_list_spinlock;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
+struct proc_dir_entry proc_scsi_aic79xx = {
+ PROC_SCSI_AIC79XX, 7, "aic79xx",
+ S_IFDIR | S_IRUGO | S_IXUGO, 2,
+ 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+#endif
+
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
/* For dynamic sglist size calculation. */
u_int ahd_linux_nseg;
static __inline int ahd_linux_map_seg(struct ahd_softc *ahd, struct scb *scb,
struct ahd_dma_seg *sg,
- dma_addr_t addr, bus_size_t len);
+ bus_addr_t addr, bus_size_t len);
static __inline void
ahd_schedule_completeq(struct ahd_softc *ahd)
static __inline void
ahd_schedule_runq(struct ahd_softc *ahd)
{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
tasklet_schedule(&ahd->platform_data->runq_tasklet);
+#else
+ /*
+ * Tasklets are not available, so run inline.
+ */
+ ahd_runq_tasklet((unsigned long)ahd);
+#endif
}
static __inline
void ahd_setup_runq_tasklet(struct ahd_softc *ahd)
{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
tasklet_init(&ahd->platform_data->runq_tasklet, ahd_runq_tasklet,
(unsigned long)ahd);
+#endif
}
static __inline void
ahd_teardown_runq_tasklet(struct ahd_softc *ahd)
{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
tasklet_kill(&ahd->platform_data->runq_tasklet);
+#endif
}
static __inline struct ahd_linux_device*
static __inline int
ahd_linux_map_seg(struct ahd_softc *ahd, struct scb *scb,
- struct ahd_dma_seg *sg, dma_addr_t addr, bus_size_t len)
+ struct ahd_dma_seg *sg, bus_addr_t addr, bus_size_t len)
{
int consumed;
sg->addr = ahd_htole32(addr & 0xFFFFFFFF);
scb->platform_data->xfer_len += len;
- if (sizeof(dma_addr_t) > 4
+ if (sizeof(bus_addr_t) > 4
&& (ahd->flags & AHD_39BIT_ADDRESSING) != 0)
len |= (addr >> 8) & AHD_SG_HIGH_ADDR_MASK;
"aic79xx: insmod or else it might trash certain memory areas.\n");
#endif
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0)
template->proc_name = "aic79xx";
+#else
+ template->proc_dir = &proc_scsi_aic79xx;
+#endif
/*
* Initialize our softc list lock prior to
{
struct ahd_softc* ahd;
struct ahd_linux_device *dev;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
u_long flags;
+#endif
ahd = (struct ahd_softc *)data;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
ahd_lock(ahd, &flags);
+#endif
while ((dev = ahd_linux_next_device_to_run(ahd)) != NULL) {
TAILQ_REMOVE(&ahd->platform_data->device_runq, dev, links);
dev->flags &= ~AHD_DEV_ON_RUN_LIST;
ahd_linux_check_device_queue(ahd, dev);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
/* Yeild to our interrupt handler */
ahd_unlock(ahd, &flags);
ahd_lock(ahd, &flags);
+#endif
}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
ahd_unlock(ahd, &flags);
+#endif
}
/******************************** Bus DMA *************************************/
int
ahd_dma_tag_create(struct ahd_softc *ahd, bus_dma_tag_t parent,
bus_size_t alignment, bus_size_t boundary,
- dma_addr_t lowaddr, dma_addr_t highaddr,
+ bus_addr_t lowaddr, bus_addr_t highaddr,
bus_dma_filter_t *filter, void *filterarg,
bus_size_t maxsize, int nsegments,
bus_size_t maxsegsz, int flags, bus_dma_tag_t *ret_tag)
{
bus_dmamap_t map;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
map = malloc(sizeof(*map), M_DEVBUF, M_NOWAIT);
if (map == NULL)
return (ENOMEM);
* our dma mask when doing allocations.
*/
if (ahd->dev_softc != NULL)
- if (pci_set_dma_mask(ahd->dev_softc, 0xFFFFFFFF)) {
+ if (ahd_pci_set_dma_mask(ahd->dev_softc, 0xFFFFFFFF)) {
printk(KERN_WARNING "aic79xx: No suitable DMA available.\n");
kfree(map);
return (ENODEV);
*vaddr = pci_alloc_consistent(ahd->dev_softc,
dmat->maxsize, &map->bus_addr);
if (ahd->dev_softc != NULL)
- if (pci_set_dma_mask(ahd->dev_softc,
+ if (ahd_pci_set_dma_mask(ahd->dev_softc,
ahd->platform_data->hw_dma_mask)) {
printk(KERN_WARNING "aic79xx: No suitable DMA available.\n");
kfree(map);
return (ENODEV);
}
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) */
+ /*
+ * At least in 2.2.14, malloc is a slab allocator so all
+ * allocations are aligned. We assume for these kernel versions
+ * that all allocations will be bellow 4Gig, physically contiguous,
+ * and accessible via DMA by the controller.
+ */
+ map = NULL; /* No additional information to store */
+ *vaddr = malloc(dmat->maxsize, M_DEVBUF, M_NOWAIT);
+#endif
if (*vaddr == NULL)
return (ENOMEM);
*mapp = map;
ahd_dmamem_free(struct ahd_softc *ahd, bus_dma_tag_t dmat,
void* vaddr, bus_dmamap_t map)
{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
pci_free_consistent(ahd->dev_softc, dmat->maxsize,
vaddr, map->bus_addr);
+#else
+ free(vaddr, M_DEVBUF);
+#endif
}
int
*/
bus_dma_segment_t stack_sg;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
stack_sg.ds_addr = map->bus_addr;
+#else
+#define VIRT_TO_BUS(a) (uint32_t)virt_to_bus((void *)(a))
+ stack_sg.ds_addr = VIRT_TO_BUS(buf);
+#endif
stack_sg.ds_len = dmat->maxsize;
cb(cb_arg, &stack_sg, /*nseg*/1, /*error*/0);
return (0);
return 1;
}
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0)
__setup("aic79xx=", aic79xx_setup);
+#endif
uint32_t aic79xx_verbose;
ahd_set_name(ahd, new_name);
}
host->unique_id = ahd->unit;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) && \
+ LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
scsi_set_pci_device(host, ahd->dev_softc);
#endif
ahd_linux_setup_user_rd_strm_settings(ahd);
ahd->platform_data->completeq_timer.data = (u_long)ahd;
ahd->platform_data->completeq_timer.function =
(ahd_linux_callback_t *)ahd_linux_thread_run_complete_queue;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
init_MUTEX_LOCKED(&ahd->platform_data->eh_sem);
init_MUTEX_LOCKED(&ahd->platform_data->dv_sem);
init_MUTEX_LOCKED(&ahd->platform_data->dv_cmd_sem);
+#else
+ ahd->platform_data->eh_sem = MUTEX_LOCKED;
+ ahd->platform_data->dv_sem = MUTEX_LOCKED;
+ ahd->platform_data->dv_cmd_sem = MUTEX_LOCKED;
+#endif
ahd_setup_runq_tasklet(ahd);
ahd->seltime = (aic79xx_seltime & 0x3) << 4;
return (0);
release_region(ahd->bshs[1].ioport, 256);
if (ahd->tags[0] == BUS_SPACE_MEMIO
&& ahd->bshs[0].maddr != NULL) {
- iounmap(ahd->bshs[0].maddr);
+ u_long base_addr;
+
+ base_addr = (u_long)ahd->bshs[0].maddr;
+ base_addr &= PAGE_MASK;
+ iounmap((void *)base_addr);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
release_mem_region(ahd->platform_data->mem_busaddr,
0x1000);
+#endif
}
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) && \
+ LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
/*
* In 2.4 we detach from the scsi midlayer before the PCI
* layer invokes our remove callback. No per-instance
cmd->use_sg, dir);
scb->platform_data->xfer_len = 0;
for (sg = scb->sg_list; nseg > 0; nseg--, cur_seg++) {
- dma_addr_t addr;
+ bus_addr_t addr;
bus_size_t len;
addr = sg_dma_address(cur_seg);
}
} else if (cmd->request_bufflen != 0) {
void *sg;
- dma_addr_t addr;
+ bus_addr_t addr;
int dir;
sg = scb->sg_list;
WARN_ON(lun != CAM_LUN_WILDCARD);
scsi_report_device_reset(ahd->platform_data->host,
channel - 'A', target);
-#else
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
Scsi_Device *scsi_dev;
/*
break;
}
case AC_BUS_RESET:
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
if (ahd->platform_data->host != NULL) {
scsi_report_bus_reset(ahd->platform_data->host,
channel - 'A');
}
+#endif
break;
default:
panic("ahd_send_async: Unexpected async event");