summaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/dma-a5k.c
blob: df02ea54e4d3e5cf3fec1ec6e31ed0b01261185e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/*
 * arch/arm/kernel/dma-a5k.c
 *
 * Copyright (C) 1998 Russell King
 *
 * DMA functions specific to A5000 architecture
 */
#include <linux/sched.h>
#include <linux/init.h>

#include <asm/dma.h>
#include <asm/fiq.h>
#include <asm/io.h>
#include <asm/hardware.h>

#include "dma.h"

static struct fiq_handler fh = { NULL, "floppydma", NULL, NULL };

int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_id)
{
	if (channel == DMA_VIRTUAL_FLOPPY)
		return 0;
	else
		return -EINVAL;
}

void arch_free_dma(dmach_t channel, dma_t *dma)
{
	if (channel != DMA_VIRTUAL_FLOPPY)
		printk("arch_free_dma: invalid channel %d\n", channel);
}

int arch_get_dma_residue(dmach_t channel, dma_t *dma)
{
	if (channel != DMA_VIRTUAL_FLOPPY)
		printk("arch_dma_count: invalid channel %d\n", channel);
	else {
		struct pt_regs regs;
		get_fiq_regs(&regs);
		return regs.ARM_r9;
	}
	return 0;
}

void arch_enable_dma(dmach_t channel, dma_t *dma)
{
	if (channel != DMA_VIRTUAL_FLOPPY)
		printk("arch_enable_dma: invalid channel %d\n", channel);
	else {
		struct pt_regs regs;
		void *fiqhandler_start;
		unsigned int fiqhandler_length;
		extern void floppy_fiqsetup(unsigned long len, unsigned long addr,
					     unsigned long port);

		if (dma->dma_mode == DMA_MODE_READ) {
			extern unsigned char floppy_fiqin_start, floppy_fiqin_end;
			fiqhandler_start = &floppy_fiqin_start;
			fiqhandler_length = &floppy_fiqin_end - &floppy_fiqin_start;
		} else {
			extern unsigned char floppy_fiqout_start, floppy_fiqout_end;
			fiqhandler_start = &floppy_fiqout_start;
			fiqhandler_length = &floppy_fiqout_end - &floppy_fiqout_start;
		}
		if (claim_fiq(&fh)) {
			printk("floppydma: couldn't claim FIQ.\n");
			return;
		}
		memcpy((void *)0x1c, fiqhandler_start, fiqhandler_length);
		regs.ARM_r9 = dma->buf.length;
		regs.ARM_r10 = __bus_to_virt(dma->buf.address);
		regs.ARM_fp = (int)PCIO_FLOPPYDMABASE;
		set_fiq_regs(&regs);
		enable_irq(dma->dma_irq);
	}
}

void arch_disable_dma(dmach_t channel, dma_t *dma)
{
	if (channel != DMA_VIRTUAL_FLOPPY)
		printk("arch_disable_dma: invalid channel %d\n", channel);
	else {
		disable_irq(dma->dma_irq);
		release_fiq(&fh);
	}
}

int arch_set_dma_speed(dmach_t channel, dma_t *dma, int cycle_ns)
{
	return 0;
}

__initfunc(void arch_dma_init(dma_t *dma))
{
	dma[DMA_VIRTUAL_FLOPPY].dma_irq = 64;
}