1 /*
2 * linux/arch/sh/kernel/io_shmse.c
3 *
4 * Copyright (C) 2003 YOSHII Takashi <yoshii-takashi@hitachi-ul.co.jp>
5 */
6
7 #include <linux/kernel.h>
8 #include <asm/hitachi_shmse.h>
9 #include <asm/io.h>
10
11 #define badio(fn, a) panic("bad i/o operation %s for %08lx.", #fn, a)
12
13 struct iop {
14 unsigned long start, end;
15 unsigned long base;
16 struct iop *(*check)(struct iop *p, unsigned long port);
17 unsigned char (*inb)(struct iop *p, unsigned long port);
18 unsigned short (*inw)(struct iop *p, unsigned long port);
19 void (*outb)(struct iop *p, unsigned char value, unsigned long port);
20 void (*outw)(struct iop *p, unsigned short value, unsigned long port);
21 };
22
simple_check(struct iop * p,unsigned long port)23 struct iop *simple_check(struct iop *p, unsigned long port){
24 if((p->start <= port) && (port <= p->end))
25 return p;
26 else
27 badio(check, port);
28 }
29
simple_inw(struct iop * p,unsigned long port)30 unsigned short simple_inw(struct iop *p, unsigned long port){
31 return *(unsigned short*)(p->base+port);
32 }
33
simple_outw(struct iop * p,unsigned short value,unsigned long port)34 void simple_outw(struct iop *p, unsigned short value, unsigned long port){
35 *(unsigned short*)(p->base+port)=value;
36 }
37
bad_inb(struct iop * p,unsigned long port)38 unsigned char bad_inb(struct iop *p, unsigned long port)
39 {
40 badio(inb, port);
41 }
42
bad_outb(struct iop * p,unsigned char value,unsigned long port)43 void bad_outb(struct iop *p, unsigned char value, unsigned long port){
44 badio(inw, port);
45 }
46
47 /* MSTLANEX01 LAN at 0xb400:0000 */
48 static struct iop laniop = {
49 .start = 0x200, // device is at 0x300, but start here for probing.
50 .end = 0x30f,
51 .base = 0xb4000000,
52 .check = simple_check,
53 .inb = bad_inb,
54 .inw = simple_inw,
55 .outb = bad_outb,
56 .outw = simple_outw,
57 };
58
port2iop(unsigned long port)59 static __inline__ struct iop *port2iop(unsigned long port){
60 if(laniop.check(&laniop, port))
61 return &laniop;
62 else
63 badio(check, port); /* XXX: dummy fallback routine? */
64 }
65
delay(void)66 static inline void delay(void)
67 {
68 ctrl_inw(0xac000000);
69 ctrl_inw(0xac000000);
70 }
71
shmse_inb(unsigned long port)72 unsigned char shmse_inb(unsigned long port)
73 {
74 struct iop *p=port2iop(port);
75 return (p->inb)(p, port);
76 }
77
shmse_inb_p(unsigned long port)78 unsigned char shmse_inb_p(unsigned long port)
79 {
80 unsigned char v=shmse_inb(port);
81 delay();
82 return v;
83 }
84
shmse_inw(unsigned long port)85 unsigned short shmse_inw(unsigned long port)
86 {
87 struct iop *p=port2iop(port);
88 return (p->inw)(p, port);
89 }
90
shmse_inl(unsigned long port)91 unsigned int shmse_inl(unsigned long port)
92 {
93 badio(inl, port);
94 }
95
shmse_outb(unsigned char value,unsigned long port)96 void shmse_outb(unsigned char value, unsigned long port)
97 {
98 struct iop *p=port2iop(port);
99 (p->outb)(p, value, port);
100 }
101
shmse_outb_p(unsigned char value,unsigned long port)102 void shmse_outb_p(unsigned char value, unsigned long port)
103 {
104 shmse_outb(value, port);
105 delay();
106 }
107
shmse_outw(unsigned short value,unsigned long port)108 void shmse_outw(unsigned short value, unsigned long port)
109 {
110 struct iop *p=port2iop(port);
111 (p->outw)(p, value, port);
112 }
113
shmse_outl(unsigned int value,unsigned long port)114 void shmse_outl(unsigned int value, unsigned long port)
115 {
116 badio(outl, port);
117 }
118
shmse_insb(unsigned long port,void * addr,unsigned long count)119 void shmse_insb(unsigned long port, void *addr, unsigned long count)
120 {
121 unsigned char *a = addr;
122 struct iop *p=port2iop(port);
123 while (count--) *a++ = (p->inb)(p, port);
124 }
125
shmse_insw(unsigned long port,void * addr,unsigned long count)126 void shmse_insw(unsigned long port, void *addr, unsigned long count)
127 {
128 unsigned short *a = addr;
129 struct iop *p=port2iop(port);
130 while (count--) *a++ = (p->inw)(p, port);
131 }
132
shmse_insl(unsigned long port,void * addr,unsigned long count)133 void shmse_insl(unsigned long port, void *addr, unsigned long count)
134 {
135 badio(insl, port);
136 }
137
shmse_outsb(unsigned long port,const void * addr,unsigned long count)138 void shmse_outsb(unsigned long port, const void *addr, unsigned long count)
139 {
140 unsigned char *a = (unsigned char*)addr;
141 struct iop *p=port2iop(port);
142 while (count--) (p->outb)(p, *a++, port);
143 }
144
shmse_outsw(unsigned long port,const void * addr,unsigned long count)145 void shmse_outsw(unsigned long port, const void *addr, unsigned long count)
146 {
147 unsigned short *a = (unsigned short*)addr;
148 struct iop *p=port2iop(port);
149 while (count--) (p->outw)(p, *a++, port);
150 }
151
shmse_outsl(unsigned long port,const void * addr,unsigned long count)152 void shmse_outsl(unsigned long port, const void *addr, unsigned long count)
153 {
154 badio(outsw, port);
155 }
156
shmse_readb(unsigned long addr)157 unsigned char shmse_readb(unsigned long addr)
158 {
159 badio(readb, addr);
160 }
161
shmse_readw(unsigned long addr)162 unsigned short shmse_readw(unsigned long addr)
163 {
164 badio(readw, addr);
165 }
166
shmse_readl(unsigned long addr)167 unsigned int shmse_readl(unsigned long addr)
168 {
169 badio(readl, addr);
170 }
171
shmse_writeb(unsigned char b,unsigned long addr)172 void shmse_writeb(unsigned char b, unsigned long addr)
173 {
174 badio(writeb, addr);
175 }
176
shmse_writew(unsigned short b,unsigned long addr)177 void shmse_writew(unsigned short b, unsigned long addr)
178 {
179 badio(writew, addr);
180 }
181
shmse_writel(unsigned int b,unsigned long addr)182 void shmse_writel(unsigned int b, unsigned long addr)
183 {
184 badio(writel, addr);
185 }
186