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