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#define TRM290_NO_DMA_WRITES
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127#include <linux/config.h>
128#include <linux/types.h>
129#include <linux/module.h>
130#include <linux/kernel.h>
131#include <linux/mm.h>
132#include <linux/ioport.h>
133#include <linux/interrupt.h>
134#include <linux/blkdev.h>
135#include <linux/init.h>
136#include <linux/hdreg.h>
137#include <linux/pci.h>
138#include <linux/delay.h>
139#include <linux/ide.h>
140
141#include <asm/io.h>
142
143#include "trm290.h"
144
145static void trm290_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
146{
147 ide_hwif_t *hwif = HWIF(drive);
148 u16 reg = 0;
149 unsigned long flags;
150
151
152 reg = use_dma ? (0x21 | 0x82) : (0x21 & ~0x82);
153
154 local_irq_save(flags);
155
156 if (reg != hwif->select_data) {
157 hwif->select_data = reg;
158
159 hwif->OUTB(0x51|(hwif->channel<<3), hwif->config_data+1);
160 hwif->OUTW(reg & 0xff, hwif->config_data);
161 }
162
163
164 if (drive->present) {
165 reg = hwif->INW(hwif->config_data + 3);
166 reg &= 0x13;
167 reg &= ~(1 << hwif->channel);
168 hwif->OUTW(reg, hwif->config_data+3);
169 }
170
171 local_irq_restore(flags);
172}
173
174static void trm290_selectproc (ide_drive_t *drive)
175{
176 trm290_prepare_drive(drive, drive->using_dma);
177}
178
179#ifdef CONFIG_BLK_DEV_IDEDMA
180static int trm290_ide_dma_write (ide_drive_t *drive )
181{
182 ide_hwif_t *hwif = HWIF(drive);
183 struct request *rq = HWGROUP(drive)->rq;
184
185 task_ioreg_t command = WIN_NOP;
186 unsigned int count, reading = 2, writing = 0;
187
188 reading = 0;
189 writing = 1;
190#ifdef TRM290_NO_DMA_WRITES
191
192 trm290_prepare_drive(drive, 0);
193 return 1;
194#endif
195 if (!(count = ide_build_dmatable(drive, rq, PCI_DMA_TODEVICE))) {
196
197 trm290_prepare_drive(drive, 0);
198 return 1;
199 }
200
201 trm290_prepare_drive(drive, 1);
202 hwif->OUTL(hwif->dmatable_dma|reading|writing, hwif->dma_command);
203 drive->waiting_for_dma = 1;
204
205 hwif->OUTW((count * 2) - 1, hwif->dma_status);
206 if (drive->media != ide_disk)
207 return 0;
208 if (HWGROUP(drive)->handler != NULL)
209 BUG();
210 ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL);
211
212
213
214#if 0
215 {
216 ide_task_t *args = rq->special;
217 command = args->tfRegister[IDE_COMMAND_OFFSET];
218 }
219#else
220 command = WIN_READDMA;
221 if (rq->cmd == IDE_DRIVE_TASKFILE) {
222 ide_task_t *args = rq->special;
223 command = args->tfRegister[IDE_COMMAND_OFFSET];
224 }
225#endif
226
227 hwif->OUTB(command, IDE_COMMAND_REG);
228 return HWIF(drive)->ide_dma_count(drive);
229}
230
231static int trm290_ide_dma_read (ide_drive_t *drive )
232{
233 ide_hwif_t *hwif = HWIF(drive);
234 struct request *rq = HWGROUP(drive)->rq;
235
236 task_ioreg_t command = WIN_NOP;
237 unsigned int count, reading = 2, writing = 0;
238
239 if (!(count = ide_build_dmatable(drive, rq, PCI_DMA_FROMDEVICE))) {
240
241 trm290_prepare_drive(drive, 0);
242 return 1;
243 }
244
245 trm290_prepare_drive(drive, 1);
246 hwif->OUTL(hwif->dmatable_dma|reading|writing, hwif->dma_command);
247 drive->waiting_for_dma = 1;
248
249 hwif->OUTW((count * 2) - 1, hwif->dma_status);
250 if (drive->media != ide_disk)
251 return 0;
252 if (HWGROUP(drive)->handler != NULL)
253 BUG();
254 ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL);
255
256
257
258#if 0
259 {
260 ide_task_t *args = rq->special;
261 command = args->tfRegister[IDE_COMMAND_OFFSET];
262 }
263#else
264 command = WIN_WRITEDMA;
265 if (rq->cmd == IDE_DRIVE_TASKFILE) {
266 ide_task_t *args = rq->special;
267 command = args->tfRegister[IDE_COMMAND_OFFSET];
268 }
269#endif
270
271 hwif->OUTB(command, IDE_COMMAND_REG);
272 return HWIF(drive)->ide_dma_count(drive);
273}
274
275static int trm290_ide_dma_begin (ide_drive_t *drive)
276{
277 return 0;
278}
279
280static int trm290_ide_dma_end (ide_drive_t *drive)
281{
282 ide_hwif_t *hwif = HWIF(drive);
283 u16 status = 0;;
284
285 drive->waiting_for_dma = 0;
286
287 ide_destroy_dmatable(drive);
288 status = hwif->INW(hwif->dma_status);
289 return (status != 0x00ff);
290}
291
292static int trm290_ide_dma_test_irq (ide_drive_t *drive)
293{
294 ide_hwif_t *hwif = HWIF(drive);
295 u16 status = 0;
296
297 status = hwif->INW(hwif->dma_status);
298 return (status == 0x00ff);
299}
300#endif
301
302
303
304
305void __init init_hwif_trm290 (ide_hwif_t *hwif)
306{
307 unsigned int cfgbase = 0;
308 unsigned long flags;
309 u8 reg = 0;
310 struct pci_dev *dev = hwif->pci_dev;
311
312 hwif->addressing = 1;
313 hwif->chipset = ide_trm290;
314 cfgbase = pci_resource_start(dev, 4);
315 if ((dev->class & 5) && cfgbase) {
316 hwif->config_data = cfgbase;
317 printk(KERN_INFO "TRM290: chip config base at 0x%04lx\n",
318 hwif->config_data);
319 } else {
320 hwif->config_data = 0x3df0;
321 printk(KERN_INFO "TRM290: using default config base at 0x%04lx\n",
322 hwif->config_data);
323 }
324
325 local_irq_save(flags);
326
327 hwif->OUTB(0x51|(hwif->channel<<3), hwif->config_data+1);
328
329 hwif->select_data = 0x21;
330 hwif->OUTB(hwif->select_data, hwif->config_data);
331
332 reg = hwif->INB(hwif->config_data+3);
333
334 reg = (reg & 0x10) | 0x03;
335 hwif->OUTB(reg, hwif->config_data+3);
336 local_irq_restore(flags);
337
338 if ((reg & 0x10))
339
340 hwif->irq = hwif->channel ? 15 : 14;
341 else if (!hwif->irq && hwif->mate && hwif->mate->irq)
342
343 hwif->irq = hwif->mate->irq;
344
345 ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->channel ? 0x0080 : 0x0000), 3);
346
347#ifdef CONFIG_BLK_DEV_IDEDMA
348 hwif->ide_dma_write = &trm290_ide_dma_write;
349 hwif->ide_dma_read = &trm290_ide_dma_read;
350 hwif->ide_dma_begin = &trm290_ide_dma_begin;
351 hwif->ide_dma_end = &trm290_ide_dma_end;
352 hwif->ide_dma_test_irq = &trm290_ide_dma_test_irq;
353#endif
354
355 hwif->selectproc = &trm290_selectproc;
356 hwif->autodma = 0;
357 hwif->drives[0].autodma = hwif->autodma;
358 hwif->drives[1].autodma = hwif->autodma;
359#if 1
360 {
361
362
363
364
365
366 u16 new, old, compat = hwif->channel ? 0x374 : 0x3f4;
367 static u16 next_offset = 0;
368 u8 old_mask;
369
370 hwif->OUTB(0x54|(hwif->channel<<3), hwif->config_data+1);
371 old = hwif->INW(hwif->config_data);
372 old &= ~1;
373 old_mask = hwif->INB(old+2);
374 if (old != compat && old_mask == 0xff) {
375
376 compat += (next_offset += 0x400);
377# if 1
378 if (check_region(compat + 2, 1))
379 printk(KERN_ERR "%s: check_region failure at 0x%04x\n",
380 hwif->name, (compat + 2));
381
382
383
384
385
386# endif
387 hwif->io_ports[IDE_CONTROL_OFFSET] = compat + 2;
388 hwif->OUTW(compat|1, hwif->config_data);
389 new = hwif->INW(hwif->config_data);
390 printk(KERN_INFO "%s: control basereg workaround: "
391 "old=0x%04x, new=0x%04x\n",
392 hwif->name, old, new & ~1);
393 }
394 }
395#endif
396}
397
398extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *);
399
400static int __devinit trm290_init_one(struct pci_dev *dev, const struct pci_device_id *id)
401{
402 ide_pci_device_t *d = &trm290_chipsets[id->driver_data];
403 if (dev->device != d->device)
404 BUG();
405 ide_setup_pci_device(dev, d);
406 MOD_INC_USE_COUNT;
407 return 0;
408}
409
410
411
412
413
414
415
416
417
418static void trm290_remove_one(struct pci_dev *dev)
419{
420 printk("trm290 removal not yet supported.\n");
421}
422
423static struct pci_device_id trm290_pci_tbl[] __devinitdata = {
424 { PCI_VENDOR_ID_TEKRAM, PCI_DEVICE_ID_TEKRAM_DC290, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
425 { 0, },
426};
427
428static struct pci_driver driver = {
429 name: "TRM290 IDE",
430 id_table: trm290_pci_tbl,
431 probe: trm290_init_one,
432 remove: __devexit_p(trm290_remove_one),
433};
434
435static int trm290_ide_init(void)
436{
437 return ide_pci_register_driver(&driver);
438}
439
440static void trm290_ide_exit(void)
441{
442 ide_pci_unregister_driver(&driver);
443}
444
445module_init(trm290_ide_init);
446module_exit(trm290_ide_exit);
447
448MODULE_AUTHOR("Mark Lord");
449MODULE_DESCRIPTION("PCI driver module for Tekram TRM290 IDE");
450MODULE_LICENSE("GPL");
451
452EXPORT_NO_SYMBOLS;
453