Import 2.3.18pre1
[davej-history.git] / include / asm-m68k / ide.h
blob5ef14f29e23d4e50a15f7e3130dcb740e794539e
1 /*
2 * linux/include/asm-m68k/ide.h
4 * Copyright (C) 1994-1996 Linus Torvalds & authors
5 */
7 /* Copyright(c) 1996 Kars de Jong */
8 /* Based on the ide driver from 1.2.13pl8 */
11 * Credits (alphabetical):
13 * - Bjoern Brauel
14 * - Kars de Jong
15 * - Torsten Ebeling
16 * - Dwight Engen
17 * - Thorsten Floeck
18 * - Roman Hodek
19 * - Guenther Kelleter
20 * - Chris Lawrence
21 * - Michael Rausch
22 * - Christian Sauer
23 * - Michael Schmitz
24 * - Jes Soerensen
25 * - Michael Thurm
26 * - Geert Uytterhoeven
29 #ifndef _M68K_IDE_H
30 #define _M68K_IDE_H
32 #ifdef __KERNEL__
34 #include <linux/config.h>
36 #include <asm/setup.h>
37 #include <asm/io.h>
38 #include <asm/irq.h>
40 #ifdef CONFIG_ATARI
41 #include <linux/interrupt.h>
42 #include <asm/atari_stdma.h>
43 #endif
45 #ifdef CONFIG_MAC
46 #include <asm/macints.h>
47 #endif
49 #ifndef MAX_HWIFS
50 #define MAX_HWIFS 4 /* same as the other archs */
51 #endif
53 int q40ide_default_irq(q40ide_ioreg_t);
55 static __inline__ int ide_default_irq(ide_ioreg_t base)
57 if (MACH_IS_Q40)
58 return q40ide_default_irq((q40ide_ioreg_t) base);
59 else return 0;
62 int q40ide_default_io_base(int);
64 static __inline__ ide_ioreg_t ide_default_io_base(int index)
66 if (MACH_IS_Q40)
67 return (ide_ioreg_t)q40ide_default_io_base(index);
68 else return 0;
72 * Can we do this in a generic manner??
74 void q40_ide_init_hwif_ports (hw_regs_t *hw, q40ide_ioreg_t data_port, q40ide_ioreg_t ctrl_port, int *irq);
77 * Set up a hw structure for a specified data port, control port and IRQ.
78 * This should follow whatever the default interface uses.
80 static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
82 #ifdef CONFIG_Q40
83 if (MACH_IS_Q40)
84 return q40_ide_init_hwif_ports(hw, (q40ide_ioreg_t) data_port, (q40ide_ioreg_t) ctrl_port, irq);
85 #endif
86 if (data_port || ctrl_port)
87 printk("ide_init_hwif_ports: must not be called\n");
91 * This registers the standard ports for this architecture with the IDE
92 * driver.
94 static __inline__ void ide_init_default_hwifs(void)
98 typedef union {
99 unsigned all : 8; /* all of the bits together */
100 struct {
101 unsigned bit7 : 1; /* always 1 */
102 unsigned lba : 1; /* using LBA instead of CHS */
103 unsigned bit5 : 1; /* always 1 */
104 unsigned unit : 1; /* drive select number, 0 or 1 */
105 unsigned head : 4; /* always zeros here */
106 } b;
107 } select_t;
109 static __inline__ int ide_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
110 unsigned long flags, const char *device, void *dev_id)
112 #ifdef CONFIG_AMIGA
113 if (MACH_IS_AMIGA)
114 return request_irq(irq, handler, 0, device, dev_id);
115 #endif /* CONFIG_AMIGA */
116 #ifdef CONFIG_Q40
117 if (MACH_IS_Q40)
118 return request_irq(irq, handler, 0, device, dev_id);
119 #endif /* CONFIG_Q40*/
120 #ifdef CONFIG_MAC
121 if (MACH_IS_MAC)
122 return request_irq(irq, handler, 0, device, dev_id);
123 #endif /* CONFIG_MAC */
124 return 0;
127 static __inline__ void ide_free_irq(unsigned int irq, void *dev_id)
129 #ifdef CONFIG_AMIGA
130 if (MACH_IS_AMIGA)
131 free_irq(irq, dev_id);
132 #endif /* CONFIG_AMIGA */
133 #ifdef CONFIG_Q40
134 if (MACH_IS_Q40)
135 free_irq(irq, dev_id);
136 #endif /* CONFIG_Q40*/
137 #ifdef CONFIG_MAC
138 if (MACH_IS_MAC)
139 free_irq(irq, dev_id);
140 #endif /* CONFIG_MAC */
144 * We should really implement those some day.
146 static __inline__ int ide_check_region (ide_ioreg_t from, unsigned int extent)
148 return 0;
151 static __inline__ void ide_request_region (ide_ioreg_t from, unsigned int extent, const char *name)
153 #ifdef CONFIG_Q40
154 if (MACH_IS_Q40)
155 request_region((q40ide_ioreg_t)from,extent,name);
156 #endif
159 static __inline__ void ide_release_region (ide_ioreg_t from, unsigned int extent)
161 #ifdef CONFIG_Q40
162 if (MACH_IS_Q40)
163 release_region((q40ide_ioreg_t)from,extent);
164 #endif
167 #undef SUPPORT_SLOW_DATA_PORTS
168 #define SUPPORT_SLOW_DATA_PORTS 0
170 #undef SUPPORT_VLB_SYNC
171 #define SUPPORT_VLB_SYNC 0
173 /* this definition is used only on startup .. */
174 #ifndef CONFIG_Q40
175 #undef HD_DATA
176 #define HD_DATA NULL
177 #else
178 #ifdef MACH_Q40_ONLY
179 #undef HD_DATA
180 #define HD_DATA ((ide_ioreg_t)0x1f0)
181 #else
182 #undef HD_DATA
183 #define HD_DATA (MACH_IS_Q40 ? (ide_ioreg_t)0x1f0 : 0)
184 #endif
185 #endif
188 #define insl(data_reg, buffer, wcount) insw(data_reg, buffer, (wcount)<<1)
189 #define outsl(data_reg, buffer, wcount) outsw(data_reg, buffer, (wcount)<<1)
191 #ifdef CONFIG_Q40
192 #ifdef MACH_Q40_ONLY
193 #define ADDR_TRANS(_addr_) (Q40_ISA_IO_W(_addr_))
194 #else
195 #define ADDR_TRANS(_addr_) (MACH_IS_Q40 ? ((unsigned char *)Q40_ISA_IO_W(_addr_)) : (_addr_))
196 #endif
197 #else
198 #define ADDR_TRANS(_addr_) (_addr_)
199 #endif
201 #define insw(port, buf, nr) ({ \
202 unsigned char *_port = (unsigned char *) ADDR_TRANS(port); \
203 unsigned char *_buf = (buf); \
204 int _nr = (nr); \
205 unsigned long _tmp; \
207 if (_nr & 15) { \
208 _tmp = (_nr & 15) - 1; \
209 asm volatile ( \
210 "1: movew %2@,%0@+; dbra %1,1b" \
211 : "=a" (_buf), "=d" (_tmp) \
212 : "a" (_port), "0" (_buf), \
213 "1" (_tmp)); \
215 if (_nr >> 4) { \
216 _tmp = (_nr >> 4) - 1; \
217 asm volatile ( \
218 "1: " \
219 "movew %2@,%0@+; " \
220 "movew %2@,%0@+; " \
221 "movew %2@,%0@+; " \
222 "movew %2@,%0@+; " \
223 "movew %2@,%0@+; " \
224 "movew %2@,%0@+; " \
225 "movew %2@,%0@+; " \
226 "movew %2@,%0@+; " \
227 "movew %2@,%0@+; " \
228 "movew %2@,%0@+; " \
229 "movew %2@,%0@+; " \
230 "movew %2@,%0@+; " \
231 "movew %2@,%0@+; " \
232 "movew %2@,%0@+; " \
233 "movew %2@,%0@+; " \
234 "movew %2@,%0@+; " \
235 "dbra %1,1b" \
236 : "=a" (_buf), "=d" (_tmp) \
237 : "a" (_port), "0" (_buf), \
238 "1" (_tmp)); \
242 #define outsw(port, buf, nr) ({ \
243 unsigned char *_port = (unsigned char *) ADDR_TRANS(port); \
244 unsigned char *_buf = (buf); \
245 int _nr = (nr); \
246 unsigned long _tmp; \
248 if (_nr & 15) { \
249 _tmp = (_nr & 15) - 1; \
250 asm volatile ( \
251 "1: movew %0@+,%2@; dbra %1,1b" \
252 : "=a" (_buf), "=d" (_tmp) \
253 : "a" (_port), "0" (_buf), \
254 "1" (_tmp)); \
256 if (_nr >> 4) { \
257 _tmp = (_nr >> 4) - 1; \
258 asm volatile ( \
259 "1: " \
260 "movew %0@+,%2@; " \
261 "movew %0@+,%2@; " \
262 "movew %0@+,%2@; " \
263 "movew %0@+,%2@; " \
264 "movew %0@+,%2@; " \
265 "movew %0@+,%2@; " \
266 "movew %0@+,%2@; " \
267 "movew %0@+,%2@; " \
268 "movew %0@+,%2@; " \
269 "movew %0@+,%2@; " \
270 "movew %0@+,%2@; " \
271 "movew %0@+,%2@; " \
272 "movew %0@+,%2@; " \
273 "movew %0@+,%2@; " \
274 "movew %0@+,%2@; " \
275 "movew %0@+,%2@; " \
276 "dbra %1,1b" \
277 : "=a" (_buf), "=d" (_tmp) \
278 : "a" (_port), "0" (_buf), \
279 "1" (_tmp)); \
283 #if defined(CONFIG_ATARI) || defined(CONFIG_Q40)
284 #define insl_swapw(data_reg, buffer, wcount) \
285 insw_swapw(data_reg, buffer, (wcount)<<1)
286 #define outsl_swapw(data_reg, buffer, wcount) \
287 outsw_swapw(data_reg, buffer, (wcount)<<1)
289 #define insw_swapw(port, buf, nr) \
290 if ((nr) % 8) \
291 __asm__ __volatile__ \
292 ("movel %0,%/a0; \
293 movel %1,%/a1; \
294 movel %2,%/d6; \
295 subql #1,%/d6; \
296 1:movew %/a0@,%/d0; \
297 rolw #8,%/d0; \
298 movew %/d0,%/a1@+; \
299 dbra %/d6,1b" : \
300 : "g" (ADDR_TRANS(port)), "g" (buf), "g" (nr) \
301 : "d0", "a0", "a1", "d6"); \
302 else \
303 __asm__ __volatile__ \
304 ("movel %0,%/a0; \
305 movel %1,%/a1; \
306 movel %2,%/d6; \
307 lsrl #3,%/d6; \
308 subql #1,%/d6; \
309 1:movew %/a0@,%/d0; \
310 rolw #8,%/d0; \
311 movew %/d0,%/a1@+; \
312 movew %/a0@,%/d0; \
313 rolw #8,%/d0; \
314 movew %/d0,%/a1@+; \
315 movew %/a0@,%/d0; \
316 rolw #8,%/d0; \
317 movew %/d0,%/a1@+; \
318 movew %/a0@,%/d0; \
319 rolw #8,%/d0; \
320 movew %/d0,%/a1@+; \
321 movew %/a0@,%/d0; \
322 rolw #8,%/d0; \
323 movew %/d0,%/a1@+; \
324 movew %/a0@,%/d0; \
325 rolw #8,%/d0; \
326 movew %/d0,%/a1@+; \
327 movew %/a0@,%/d0; \
328 rolw #8,%/d0; \
329 movew %/d0,%/a1@+; \
330 movew %/a0@,%/d0; \
331 rolw #8,%/d0; \
332 movew %/d0,%/a1@+; \
333 dbra %/d6,1b" : \
334 : "g" (ADDR_TRANS(port)), "g" (buf), "g" (nr) \
335 : "d0", "a0", "a1", "d6")
338 #define outsw_swapw(port, buf, nr) \
339 if ((nr) % 8) \
340 __asm__ __volatile__ \
341 ("movel %0,%/a0; \
342 movel %1,%/a1; \
343 movel %2,%/d6; \
344 subql #1,%/d6; \
345 1:movew %/a1@+,%/d0; \
346 rolw #8,%/d0; \
347 movew %/d0,%/a0@; \
348 dbra %/d6,1b" : \
349 : "g" (ADDR_TRANS(port)), "g" (buf), "g" (nr) \
350 : "d0", "a0", "a1", "d6"); \
351 else \
352 __asm__ __volatile__ \
353 ("movel %0,%/a0; \
354 movel %1,%/a1; \
355 movel %2,%/d6; \
356 lsrl #3,%/d6; \
357 subql #1,%/d6; \
358 1:movew %/a1@+,%/d0; \
359 rolw #8,%/d0; \
360 movew %/d0,%/a0@; \
361 movew %/a1@+,%/d0; \
362 rolw #8,%/d0; \
363 movew %/d0,%/a0@; \
364 movew %/a1@+,%/d0; \
365 rolw #8,%/d0; \
366 movew %/d0,%/a0@; \
367 movew %/a1@+,%/d0; \
368 rolw #8,%/d0; \
369 movew %/d0,%/a0@; \
370 movew %/a1@+,%/d0; \
371 rolw #8,%/d0; \
372 movew %/d0,%/a0@; \
373 movew %/a1@+,%/d0; \
374 rolw #8,%/d0; \
375 movew %/d0,%/a0@; \
376 movew %/a1@+,%/d0; \
377 rolw #8,%/d0; \
378 movew %/d0,%/a0@; \
379 movew %/a1@+,%/d0; \
380 rolw #8,%/d0; \
381 movew %/d0,%/a0@; \
382 dbra %/d6,1b" : \
383 : "g" (ADDR_TRANS(port)), "g" (buf), "g" (nr) \
384 : "d0", "a0", "a1", "d6")
386 #endif /* CONFIG_ATARI */
388 #define T_CHAR (0x0000) /* char: don't touch */
389 #define T_SHORT (0x4000) /* short: 12 -> 21 */
390 #define T_INT (0x8000) /* int: 1234 -> 4321 */
391 #define T_TEXT (0xc000) /* text: 12 -> 21 */
393 #define T_MASK_TYPE (0xc000)
394 #define T_MASK_COUNT (0x3fff)
396 #define D_CHAR(cnt) (T_CHAR | (cnt))
397 #define D_SHORT(cnt) (T_SHORT | (cnt))
398 #define D_INT(cnt) (T_INT | (cnt))
399 #define D_TEXT(cnt) (T_TEXT | (cnt))
401 #if defined(CONFIG_AMIGA) || defined (CONFIG_MAC)
402 static u_short driveid_types[] = {
403 D_SHORT(10), /* config - vendor2 */
404 D_TEXT(20), /* serial_no */
405 D_SHORT(3), /* buf_type, buf_size - ecc_bytes */
406 D_TEXT(48), /* fw_rev - model */
407 D_CHAR(2), /* max_multsect - vendor3 */
408 D_SHORT(1), /* dword_io */
409 D_CHAR(2), /* vendor4 - capability */
410 D_SHORT(1), /* reserved50 */
411 D_CHAR(4), /* vendor5 - tDMA */
412 D_SHORT(4), /* field_valid - cur_sectors */
413 D_INT(1), /* cur_capacity */
414 D_CHAR(2), /* multsect - multsect_valid */
415 D_INT(1), /* lba_capacity */
416 D_SHORT(194) /* dma_1word - reservedyy */
419 #define num_driveid_types (sizeof(driveid_types)/sizeof(*driveid_types))
420 #endif /* CONFIG_AMIGA */
422 static __inline__ void ide_fix_driveid(struct hd_driveid *id)
424 #if defined(CONFIG_AMIGA) || defined (CONFIG_MAC)
425 u_char *p = (u_char *)id;
426 int i, j, cnt;
427 u_char t;
429 if (!MACH_IS_AMIGA && !MACH_IS_MAC)
430 return;
431 for (i = 0; i < num_driveid_types; i++) {
432 cnt = driveid_types[i] & T_MASK_COUNT;
433 switch (driveid_types[i] & T_MASK_TYPE) {
434 case T_CHAR:
435 p += cnt;
436 break;
437 case T_SHORT:
438 for (j = 0; j < cnt; j++) {
439 t = p[0];
440 p[0] = p[1];
441 p[1] = t;
442 p += 2;
444 break;
445 case T_INT:
446 for (j = 0; j < cnt; j++) {
447 t = p[0];
448 p[0] = p[3];
449 p[3] = t;
450 t = p[1];
451 p[1] = p[2];
452 p[2] = t;
453 p += 4;
455 break;
456 case T_TEXT:
457 for (j = 0; j < cnt; j += 2) {
458 t = p[0];
459 p[0] = p[1];
460 p[1] = t;
461 p += 2;
463 break;
466 #endif /* CONFIG_AMIGA */
469 static __inline__ void ide_release_lock (int *ide_lock)
471 #ifdef CONFIG_ATARI
472 if (MACH_IS_ATARI) {
473 if (*ide_lock == 0) {
474 printk("ide_release_lock: bug\n");
475 return;
477 *ide_lock = 0;
478 stdma_release();
480 #endif /* CONFIG_ATARI */
483 static __inline__ void ide_get_lock (int *ide_lock, void (*handler)(int, void *, struct pt_regs *), void *data)
485 #ifdef CONFIG_ATARI
486 if (MACH_IS_ATARI) {
487 if (*ide_lock == 0) {
488 if (in_interrupt() > 0)
489 panic( "Falcon IDE hasn't ST-DMA lock in interrupt" );
490 stdma_lock(handler, data);
491 *ide_lock = 1;
494 #endif /* CONFIG_ATARI */
497 #define ide_ack_intr(hwif) ((hwif)->hw.ack_intr ? (hwif)->hw.ack_intr(hwif) : 1)
500 * On the Atari, we sometimes can't enable interrupts:
503 /* MSch: changed sti() to STI() wherever possible in ide.c; moved STI() def.
504 * to asm/ide.h
506 /* The Atari interrupt structure strictly requires that the IPL isn't lowered
507 * uncontrolled in an interrupt handler. In the concrete case, the IDE
508 * interrupt is already a slow int, so the irq is already disabled at the time
509 * the handler is called, and the IPL has been lowered to the minimum value
510 * possible. To avoid going below that, STI() checks for being called inside
511 * an interrupt, and in that case it does nothing. Hope that is reasonable and
512 * works. (Roman)
514 #ifdef MACH_ATARI_ONLY
515 #define ide__sti() \
516 do { \
517 if (!in_interrupt()) __sti(); \
518 } while(0)
519 #elif defined(CONFIG_ATARI)
520 #define ide__sti() \
521 do { \
522 if (!MACH_IS_ATARI || !in_interrupt()) sti(); \
523 } while(0)
524 #else /* !defined(CONFIG_ATARI) */
525 #define ide__sti() __sti()
526 #endif
528 #endif /* __KERNEL__ */
530 #endif /* _M68K_IDE_H */