summaryrefslogtreecommitdiffstats
path: root/bsps/powerpc/beatnik/net/porting/rtemscompat.h
blob: 5a4bb6bea25dcdf4e5d74b1c4bbf4d7b8676df61 (plain) (blame)
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
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
#ifndef RTEMS_COMPAT_BSD_NET_H
#define RTEMS_COMPAT_BSD_NET_H

/* BSD -> rtems wrappers; stuff that must be defined
 *        prior to including most BSD headers
 */

/* Copyright: Till Straumann <strauman@slac.stanford.edu>, 2005;
 * License:   see LICENSE file.
 */

#include <rtems.h>
#include <sys/errno.h>
#include <sys/types.h>

#include <stdlib.h>

/* Check for RTEMS version; true if >= ma.mi.re */
#define ISMINVERSION(ma,mi,re) \
	(    __RTEMS_MAJOR__  > (ma)	\
	 || (__RTEMS_MAJOR__ == (ma) && __RTEMS_MINOR__  > (mi))	\
	 || (__RTEMS_MAJOR__ == (ma) && __RTEMS_MINOR__ == (mi) && __RTEMS_REVISION__ >= (re)) \
    )

/* 'align' ARG is evaluated more than once */
#define _DO_ALIGN(addr, align) (((uint32_t)(addr) + (align) - 1) & ~((align)-1))


/* malloc/free are redefined :-( */
static inline void *the_real_malloc(size_t n)
{
	return malloc(n);
}

static inline void  the_real_free(void *p)
{
	return free(p);
}

#include <machine/rtems-bsd-kernel-space.h>
#include <rtems/rtems_bsdnet.h>
#include <rtems/rtems_bsdnet_internal.h>
#ifdef __i386__
#include <libcpu/cpu.h>
#elif defined(__PPC__)
#include <libcpu/io.h>
#else
#error "dunno what IO ops to use on this architecture"
#endif
#include <rtems/bspIo.h>

#define NET_EMB(x,y,z) x ## y ## z
#define NET_EMBEMB(x,y,z) NET_EMB(x,y,z)

#define NET_STR(arg)	#arg
#define NET_STRSTR(arg)	NET_STR(arg)

#define NET_SOFTC 	NET_EMBEMB(,NETDRIVER_PREFIX,_softc)

#define METHODS     NET_EMBEMB(rtems_,NETDRIVER_PREFIX,_methods)
extern struct _net_drv_tbl METHODS;

#ifdef DEBUG_MODULAR
#define METHODSPTR  NET_EMBEMB(rtems_,NETDRIVER_PREFIX,_methods_p)
extern struct _net_drv_tbl *volatile METHODSPTR;
#else
#define METHODSPTR  (&METHODS)
#endif

#if defined(__LITTLE_ENDIAN__) || (__i386__)
static inline uint16_t  htole16(uint16_t  v) { return v; }
static inline uint32_t  htole32(uint32_t  v) { return v; }
static inline uint64_t  htole64(uint64_t  v) { return v; }
static inline uint16_t  le16toh(uint16_t  v) { return v; }
static inline uint32_t  le32toh(uint32_t  v) { return v; }
static inline uint64_t  le64toh(uint64_t  v) { return v; }
#elif defined(__BIG_ENDIAN__)
#ifdef __PPC__
#include <libcpu/byteorder.h>

/* Different RTEMS versions use different types
 * for 32-bit (unsigned vs. unsigned long which
 * always cause gcc warnings and possible alias
 * violations, sigh).
 */

#if ISMINVERSION(4,8,0)
typedef uint32_t rtemscompat_32_t;
#else
typedef unsigned rtemscompat_32_t;
#endif

static inline uint16_t
htole16(uint16_t v)
{
uint16_t rval;
	st_le16(&rval,v);
	return rval;
}

static inline uint16_t
le16toh(uint16_t v)
{
	return ld_le16((unsigned short*)&v);
}

static inline uint32_t
htole32(uint32_t v)
{
rtemscompat_32_t rval;
	st_le32(&rval,v);
	return rval;
}

static inline uint32_t
le32toh(uint32_t v)
{
rtemscompat_32_t vv = v;
	return ld_le32(&vv);
}

/* Compiler generated floating point instructions for this
 * and rtems_bsdnet_newproc()-generated tasks are non-FP
 * :-(
 */
static inline uint64_t
htole64(uint64_t  v) 
{
union {
	rtemscompat_32_t tmp[2];
	uint64_t          rval;
} u;

	st_le32( &u.tmp[0], (unsigned)(v&0xffffffff) );
	st_le32( &u.tmp[1], (unsigned)((v>>32)&0xffffffff) );

	return u.rval;
}

#else
#error "need htoleXX() implementation for this CPU arch"
#endif

#else
#error "Unknown CPU endianness"
#endif



#ifdef __PPC__
#define _out_byte(a,v) out_8((volatile uint8_t*)(a),(v))
#define _inp_byte(a)   in_8((volatile uint8_t*)(a))
#ifdef NET_CHIP_LE
#define _out_word(a,v) out_le16((volatile uint16_t*)(a),(v))
#define _out_long(a,v) out_le32((volatile uint32_t *)(a),(v))
#define _inp_word(a)   in_le16((volatile uint16_t*)(a))
#define _inp_long(a)   in_le32((volatile uint32_t *)(a))
#elif defined(NET_CHIP_BE)
#define _out_word(a,v) out_be16((volatile uint16_t*)(a),(v))
#define _out_long(a,v) out_be32((volatile uint32_t *)(a),(v))
#define _inp_word(a)   in_be16((volatile uint16_t*)(a))
#define _inp_long(a)   in_be32((volatile uint32_t *)(a))
#else
#error rtemscompat_defs.h must define either NET_CHIP_LE or NET_CHIP_BE
#endif
static inline void wrle32(unsigned *a, unsigned v)
{
	asm volatile("stwbrx %1,0,%2":"=m"(*a):"r"(v),"r"(a));
}
static inline unsigned rdle32(unsigned *a)
{
	asm volatile("lwbrx %0,0,%0":"=r"(a):"0"(a),"m"(*a));
	return (unsigned)a;
}
static inline void orle32(unsigned *a,unsigned v) { wrle32(a, rdle32(a) | v); }
static inline void anle32(unsigned *a,unsigned v) { wrle32(a, rdle32(a) & v); }

static inline void wrle16(unsigned short *a, unsigned short v)
{
	asm volatile("sthbrx %1,0,%2":"=m"(*a):"r"(v),"r"(a));
}
static inline unsigned short rdle16(unsigned short *a)
{
	asm volatile("lhbrx %0,0,%0":"=r"(a):"0"(a),"m"(*a));
	return (unsigned short)(unsigned)a;
}
static inline void orle16(unsigned short *a,unsigned short v) { wrle16(a, rdle16(a) | v); }
static inline void anle16(unsigned short *a,unsigned short v) { wrle16(a, rdle16(a) & v); }
#endif

#ifdef __i386__
#ifdef NET_CHIP_BE
#error dunno how to output BE data
#endif

static inline void wrle32(volatile unsigned *p, unsigned v) { *p  = v; }
static inline void orle32(volatile unsigned *p, unsigned v) { *p |= v; }
static inline void anle32(volatile unsigned *p, unsigned v) { *p &= v; }
static inline unsigned rdle32(volatile unsigned *p) { return *p; }

static inline void wrle16(volatile unsigned short *p, unsigned short v) { *p  = v; }
static inline void orle16(volatile unsigned short *p, unsigned short v) { *p |= v; }
static inline void anle16(volatile unsigned short *p, unsigned short v) { *p &= v; }
static inline unsigned short rdle16(volatile unsigned short *p) { return *p; }

#ifdef NET_CHIP_MEM_IO

#ifdef __i386__
static inline void           _out_byte(unsigned a, unsigned char v)  {        *(volatile unsigned char*)a = v; }
static inline unsigned char  _inp_byte(unsigned a)                   { return *(volatile unsigned char*)a;     }
#ifdef NET_CHIP_LE
static inline void           _out_word(unsigned a, unsigned short v) {        *(volatile unsigned short*)a = v; }
static inline unsigned short _inp_word(unsigned a)                   { return *(volatile unsigned short*)a;     }
static inline void           _out_long(unsigned a, unsigned v)       {        *(volatile unsigned      *)a = v; }
static inline unsigned       _inp_long(unsigned a)                   { return *(volatile unsigned      *)a; }
#elif defined(NET_CHIP_BE)
#error "BE memory IO not implemented for i386 yet"
#else
#error rtemscompat_defs.h must define either NET_CHIP_LE or NET_CHIP_BE
#endif
#else

#error "Memory IO not implemented for this CPU architecture yet"

#endif
#elif defined(NET_CHIP_PORT_IO)
#define _out_byte(addr,val) outport_byte((addr),(val))
#define _out_word(addr,val) outport_word((addr),(val))
#define _out_long(addr,val) outport_long((addr),(val))

static inline u_int8_t _inp_byte(volatile unsigned char *a)
{
register u_int8_t rval;
	inport_byte((unsigned short)(unsigned)a,rval);
	return rval;
}
static inline u_int16_t _inp_word(volatile unsigned short *a)
{
register u_int16_t rval;
	inport_word((unsigned short)(unsigned)a,rval);
	return rval;
}
static inline u_int32_t _inp_long(volatile unsigned *a)
{
register u_int32_t rval;
	inport_long((unsigned short)(unsigned)a,rval);
	return rval;
}
#else
#error either NET_CHIP_MEM_IO or NET_CHIP_PORT_IO must be defined
#endif
#endif

#ifndef __FBSDID
#define __FBSDID(arg)
#endif

#define device_printf(device,format,args...) printk(format,## args)

static inline u_int8_t bus_space_do_read_1(u_long handle, unsigned reg)
{
	return _inp_byte((volatile unsigned char*)((handle)+(reg)));
}

static inline u_int16_t bus_space_do_read_2(u_long handle, unsigned reg)
{
	return _inp_word((volatile unsigned short*)((handle)+(reg)));
}

static inline u_int32_t bus_space_do_read_4(u_long handle, unsigned reg)
{
	return _inp_long((volatile unsigned *)((handle)+(reg)));
}

#define bus_space_read_1(tag,handle,reg) bus_space_do_read_1((handle),(reg))
#define bus_space_read_2(tag,handle,reg) bus_space_do_read_2((handle),(reg))
#define bus_space_read_4(tag,handle,reg) bus_space_do_read_4((handle),(reg))

static inline void bus_space_do_write_multi_1(u_long handle, unsigned reg, unsigned char *addr, int cnt)
{
	int i; for (i=0; i<cnt; i++) _out_byte( (handle) + (reg), (addr)[i]);
}

static inline void bus_space_do_write_multi_2(u_long handle, unsigned reg, unsigned short *addr, int cnt)
{
	int i; for (i=0; i<cnt; i++) _out_word( (handle) + (reg), (addr)[i]);
}

static inline void bus_space_do_write_multi_4(u_long handle, unsigned reg, unsigned long *addr, int cnt)
{
	int i; for (i=0; i<cnt; i++) _out_long( (handle) + (reg), (addr)[i]);
}


#define bus_space_write_multi_1(tag, handle, reg, addr, cnt) \
		bus_space_do_write_multi_1(handle, reg, addr, cnt)
#define bus_space_write_multi_2(tag, handle, reg, addr, cnt) \
		bus_space_do_write_multi_2(handle, reg, addr, cnt)
#define bus_space_write_multi_4(tag, handle, reg, addr, cnt) \
		bus_space_do_write_multi_4(handle, reg, addr, cnt)

static inline void bus_space_do_read_multi_1(u_long handle, unsigned reg, unsigned char *addr, int cnt)
{
	int i; for (i=0; i<cnt; i++)
				(addr)[i] = _inp_byte((volatile unsigned char*)((handle)+(reg)));
}

static inline void bus_space_do_read_multi_2(u_long handle, unsigned reg, unsigned short *addr, int cnt)
{
	int i; for (i=0; i<cnt; i++)
				(addr)[i] = _inp_word((volatile unsigned short*)((handle)+(reg)));
}

static inline void bus_space_do_read_multi_4(u_long handle, unsigned reg, unsigned long *addr, int cnt)
{
	int i; for (i=0; i<cnt; i++)
				(addr)[i] = _inp_long((volatile unsigned *)((handle)+(reg)));
}

#define bus_space_read_multi_1(tag, handle, reg, addr, cnt) \
		bus_space_do_read_multi_1(handle, reg, addr, cnt)
#define bus_space_read_multi_2(tag, handle, reg, addr, cnt) \
		bus_space_do_read_multi_2(handle, reg, addr, cnt)
#define bus_space_read_multi_4(tag, handle, reg, addr, cnt) \
		bus_space_do_read_multi_4(handle, reg, addr, cnt)



#define bus_space_write_1(tag, handle, reg, val) \
	do { _out_byte( (handle) + (reg), (val)); } while (0)

#define bus_space_write_2(tag, handle, reg, val) \
	do { _out_word( (handle) + (reg), (val)); } while (0)

#define bus_space_write_4(tag, handle, reg, val) \
	do { _out_long( (handle) + (reg), (val)); } while (0)

#define BPF_MTAP(a,b)	do { } while (0)

extern unsigned net_driver_ticks_per_sec;

#ifdef __PPC__
/* PPC has a timebase - based delay */
#define DELAY(n) do {		\
	if ( (n) > 10000 )		\
		rtems_task_wake_after((((n)*net_driver_ticks_per_sec)/1000000) + 1);	\
	else					\
		rtems_bsp_delay(n);	\
	} while (0)
#else
#warning "Have no good usec delay implementation"
#define DELAY(n) do {		\
		rtems_task_wake_after((((n)*net_driver_ticks_per_sec)/1000000) + 1);	\
	} while (0)
#endif


#define IRQ_LOCKED(code) \
	do { unsigned long _xtre_irq_flags; \
		rtems_interrupt_disable(_xtre_irq_flags); \
			do { code } while(0); 	\
		rtems_interrupt_enable(_xtre_irq_flags); \
	} while (0)

typedef void (driver_intr_t)(void *);

#define if_xname if_name

/* need to replace those with LOCAL2PCI() and make sure the bus handle is initialized
 * (on most BSPs we get away with PCI_DRAM_OFFSET [no bus handle needed at all]
 */
#ifndef PCI_DRAM_OFFSET
#define PCI_DRAM_OFFSET 0
#endif

#ifndef PCI_MEM_BASE
#define PCI_MEM_BASE    0
#endif

#define kvtop(a)			((unsigned long)(a) + PCI_DRAM_OFFSET)
#define vtophys(a)			((unsigned long)(a) + PCI_DRAM_OFFSET)

#define PCI2LOCAL(a,bus)	((unsigned long)(a) + PCI_MEM_BASE)

#ifdef PCI0_IO_BASE /* special mvme5500 hack :-( */
#define PCI_IO_2LOCAL(a,bus) ((unsigned long)(a) + PCI0_IO_BASE)
#elif defined(PCI_IO_BASE)
#define PCI_IO_2LOCAL(a,bus) ((unsigned long)(a) + PCI_IO_BASE)
#elif defined(_IO_BASE)
#define PCI_IO_2LOCAL(a,bus) ((unsigned long)(a) + _IO_BASE)
#else
#warning "Unable to determine base address of PCI IO space; using ZERO"
#define PCI_IO_2LOCAL(a,bus) ((unsigned long)(a))
#endif

#define if_printf(if,fmt,args...)  printf("%s:"fmt,(if)->if_name,args)

#ifndef BUS_PROBE_DEFAULT
#define BUS_PROBE_DEFAULT 0
#endif

static inline void *
contigmalloc(
	unsigned long size,
	int type,
	int flags,
	unsigned long lo,
	unsigned long hi,
	unsigned long align,
	unsigned long bound)
{
void *ptr  = rtems_bsdnet_malloc(size + sizeof(ptr) + align-1, type, flags);
char *rval = 0;
	if ( ptr ) {
		unsigned tmp = (unsigned)ptr + align - 1;
		tmp -= tmp % align;
		rval = (char*)tmp;
		/* save backlink */
		*(void**)(rval+size) =  ptr;
	}
	return rval;
}

static inline void
contigfree(void *ptr, size_t size, int type)
{
	rtems_bsdnet_free( *(void**)((unsigned)ptr + size), type);
}

/* callout stuff */
#define callout_init(args...) do {} while (0);
#define callout_reset(args...) do {} while (0);
#define callout_stop(args...) do {} while (0);

#define IFQ_DRV_IS_EMPTY(q) (0 == (q)->ifq_head)
#define IFQ_DRV_DEQUEUE(q,m) IF_DEQUEUE((q),(m))
#define IFQ_DRV_PREPEND(q,m) IF_PREPEND((q),(m))

#define DO_ETHER_INPUT_SKIPPING_ETHER_HEADER(ifp,m)				\
		{	struct ether_header *eh;							\
			eh				  = mtod(m, struct ether_header*);	\
       		m->m_data        += sizeof(struct ether_header);	\
        	m->m_len         -= sizeof(struct ether_header);	\
        	m->m_pkthdr.len  -= sizeof(struct ether_header);	\
			m->m_pkthdr.rcvif = ifp;							\
    		ether_input(ifp, eh, m);							\
		} while (0)


#ifndef __KERNEL_RCSID
#define __KERNEL_RCSID(arg...) 
#endif

#endif