This source file includes following definitions.
- a3000_intr
- dma_setup
- dma_stop
- a3000_detect
1 #include <linux/types.h>
2 #include <linux/mm.h>
3 #include <linux/blk.h>
4 #include <linux/version.h>
5
6 #include <asm/page.h>
7 #include <asm/pgtable.h>
8 #include <asm/bootinfo.h>
9 #include <asm/amigaints.h>
10 #include <asm/amigahw.h>
11 #include <asm/irq.h>
12
13 #include "scsi.h"
14 #include "hosts.h"
15 #include "wd33c93.h"
16 #include "a3000.h"
17
18 #include<linux/stat.h>
19
20 struct proc_dir_entry proc_scsi_a3000 = {
21 PROC_SCSI_A3000, 5, "A3000",
22 S_IFDIR | S_IRUGO | S_IXUGO, 2
23 };
24
25 #define DMA(ptr) ((a3000_scsiregs *)((ptr)->base))
26 #define HDATA(ptr) ((struct WD33C93_hostdata *)((ptr)->hostdata))
27
28 static struct Scsi_Host *a3000_host = NULL;
29
30 static void a3000_intr (int irq, struct pt_regs *fp, void *dummy)
31 {
32 unsigned int status = DMA(a3000_host)->ISTR;
33
34 if (!(status & ISTR_INT_P))
35 return;
36
37 if (status & ISTR_INTS)
38 {
39
40 custom.intena = IF_PORTS;
41 wd33c93_intr (a3000_host);
42
43 custom.intena = IF_SETCLR | IF_PORTS;
44 } else {
45 printk("Non-serviced A3000 SCSI-interrupt? ISTR = %02x\n", status);
46 }
47 }
48
49 static int dma_setup (Scsi_Cmnd *cmd, int dir_in)
50 {
51 unsigned short cntr = CNTR_PDMD | CNTR_INTEN;
52 unsigned long addr = VTOP(cmd->SCp.ptr);
53
54
55
56
57
58
59
60 if (addr & A3000_XFER_MASK ||
61 (!dir_in && mm_end_of_chunk (addr, cmd->SCp.this_residual)))
62 {
63 HDATA(a3000_host)->dma_bounce_len = (cmd->SCp.this_residual + 511)
64 & ~0x1ff;
65 HDATA(a3000_host)->dma_bounce_buffer =
66 scsi_malloc (HDATA(a3000_host)->dma_bounce_len);
67
68
69 if (!HDATA(a3000_host)->dma_bounce_buffer) {
70 HDATA(a3000_host)->dma_bounce_len = 0;
71 return 1;
72 }
73
74 if (!dir_in) {
75
76 if (cmd->use_sg) {
77 memcpy (HDATA(a3000_host)->dma_bounce_buffer,
78 cmd->SCp.ptr, cmd->SCp.this_residual);
79 } else
80 memcpy (HDATA(a3000_host)->dma_bounce_buffer,
81 cmd->request_buffer, cmd->request_bufflen);
82 }
83
84 addr = VTOP(HDATA(a3000_host)->dma_bounce_buffer);
85 }
86
87
88 if (!dir_in)
89 cntr |= CNTR_DDIR;
90
91
92 HDATA(a3000_host)->dma_dir = dir_in;
93
94 DMA(a3000_host)->CNTR = cntr;
95
96
97 DMA(a3000_host)->ACR = addr;
98
99
100 if (dir_in)
101 {
102
103
104
105
106
107
108
109
110 if (boot_info.cputype & CPU_68040)
111 cache_push (addr, cmd->SCp.this_residual);
112 else
113 cache_clear (addr, cmd->SCp.this_residual);
114 }
115 else
116
117 cache_push (addr, cmd->SCp.this_residual);
118
119
120
121 DMA(a3000_host)->ST_DMA = 1;
122
123
124 return 0;
125 }
126
127 static void dma_stop (struct Scsi_Host *instance, Scsi_Cmnd *SCpnt,
128 int status)
129 {
130
131 unsigned short cntr = CNTR_PDMD;
132
133 if (!HDATA(instance)->dma_dir)
134 cntr |= CNTR_DDIR;
135
136 DMA(instance)->CNTR = cntr;
137
138
139 if (HDATA(instance)->dma_dir) {
140 DMA(instance)->FLUSH = 1;
141 while (!(DMA(instance)->ISTR & ISTR_FE_FLG))
142 ;
143 }
144
145
146
147
148
149 DMA(instance)->CINT = 1;
150
151
152 DMA(instance)->SP_DMA = 1;
153
154
155 DMA(instance)->CNTR = CNTR_PDMD | CNTR_INTEN;
156
157
158 if (status && HDATA(instance)->dma_bounce_buffer) {
159 if (SCpnt && SCpnt->use_sg) {
160 if (HDATA(instance)->dma_dir && SCpnt)
161 memcpy (SCpnt->SCp.ptr,
162 HDATA(instance)->dma_bounce_buffer,
163 SCpnt->SCp.this_residual);
164 scsi_free (HDATA(instance)->dma_bounce_buffer,
165 HDATA(instance)->dma_bounce_len);
166 HDATA(instance)->dma_bounce_buffer = NULL;
167 HDATA(instance)->dma_bounce_len = 0;
168 } else {
169 if (HDATA(instance)->dma_dir && SCpnt)
170 memcpy (SCpnt->request_buffer,
171 HDATA(instance)->dma_bounce_buffer,
172 SCpnt->request_bufflen);
173
174 scsi_free (HDATA(instance)->dma_bounce_buffer,
175 HDATA(instance)->dma_bounce_len);
176 HDATA(instance)->dma_bounce_buffer = NULL;
177 HDATA(instance)->dma_bounce_len = 0;
178 }
179 }
180 }
181
182 int a3000_detect(Scsi_Host_Template *tpnt)
183 {
184 static unsigned char called = 0;
185
186 if (called)
187 return 0;
188
189 if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(A3000_SCSI))
190 return 0;
191
192 tpnt->proc_dir = &proc_scsi_a3000;
193
194 a3000_host = scsi_register (tpnt, sizeof(struct WD33C93_hostdata));
195 a3000_host->base = (unsigned char *)ZTWO_VADDR(0xDD0000);
196 DMA(a3000_host)->DAWR = DAWR_A3000;
197 wd33c93_init(a3000_host, (wd33c93_regs *)&(DMA(a3000_host)->SASR),
198 dma_setup, dma_stop, WD33C93_FS_12_15);
199 add_isr(IRQ_AMIGA_PORTS, a3000_intr, 0, NULL, "A3000 SCSI");
200 DMA(a3000_host)->CNTR = CNTR_PDMD | CNTR_INTEN;
201 called = 1;
202
203 return 1;
204 }