1/**************************************************************************
2
3Copyright (c) 2001-2003, Intel Corporation
4All rights reserved.
5
6Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions are met:
8
9 1. Redistributions of source code must retain the above copyright notice,
10    this list of conditions and the following disclaimer.
11
12 2. Redistributions in binary form must reproduce the above copyright
13    notice, this list of conditions and the following disclaimer in the
14    documentation and/or other materials provided with the distribution.
15
16 3. Neither the name of the Intel Corporation nor the names of its
17    contributors may be used to endorse or promote products derived from
18    this software without specific prior written permission.
19
20THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30POSSIBILITY OF SUCH DAMAGE.
31
32***************************************************************************/
33
34#ifndef _IF_EM_OSDEP_H_
35#define _IF_EM_OSDEP_H_
36
37#include "driver.h"
38#include "device.h"
39#include "timer.h"
40#include "debug.h"
41
42#include <OS.h>
43#include <KernelExport.h>
44#include <ByteOrder.h>
45
46#include <stdlib.h>
47#include <string.h>
48#include <stdint.h>
49#include <sys/types.h>
50
51#define usec_delay(x) snooze(x)
52#define msec_delay(x) snooze(1000*(x))
53
54// no longer used in FreeBSD
55#define splx(s)
56#define splimp() 0
57
58#ifndef bzero
59  #define bzero(d,c)		memset((d), (0), (c))
60#endif
61#ifndef bcopy
62  #define bcopy(s,d,c)		memmove((d), (s), (c))
63#endif
64#ifndef bcmp
65  #define bcmp(p1, p2, s)	memcmp((p1), (p2), (s)) // XXX correct order?
66#endif
67
68#define TUNABLE_INT(a, b)	/* ignored */
69
70#define FALSE               0
71#define TRUE                1
72
73#define hz					1000000LL
74
75typedef bool	boolean_t;
76typedef unsigned long vm_offset_t;
77
78
79struct em_osdep
80{
81	ipro1000_device *dev;
82};
83
84typedef ipro1000_device * device_t;
85
86#define PCIR_COMMAND			PCI_command
87#define PCIR_REVID				PCI_revision
88#define PCIR_SUBVEND_0			PCI_subsystem_vendor_id
89#define PCIR_SUBDEV_0			PCI_subsystem_id
90#define PCIM_CMD_IOEN			0x0001
91#define PCIM_CMD_MEMEN			0x0002
92#define PCIM_CMD_BUSMASTEREN	0x0004
93#define CMD_MEM_WRT_INVALIDATE          0x0010  /* BIT_4 */
94
95#define pci_read_config(dev, offset, size) \
96	gPci->read_pci_config(dev->pciBus, dev->pciDev, dev->pciFunc, offset, size)
97
98#define pci_write_config(dev, offset, value, size) \
99	gPci->write_pci_config(dev->pciBus, dev->pciDev, dev->pciFunc, offset, size, value)
100
101#define pci_get_vendor(dev) \
102	gPci->read_pci_config(dev->pciBus, dev->pciDev, dev->pciFunc, PCI_vendor_id, 2)
103
104#define pci_get_device(dev) \
105	gPci->read_pci_config(dev->pciBus, dev->pciDev, dev->pciFunc, PCI_device_id, 2)
106
107#define inl(port) \
108	gPci->read_io_32(port)
109
110#define outl(port, value) \
111	gPci->write_io_32(port, value)
112
113
114void *contigmalloc(int size, int p1, int p2, int p3, int p4, int p5, int p6);
115void contigfree(void *p, int p1, int p2);
116
117static inline u_int64_t vtophys(unsigned long virtual_addr)
118{
119	physical_entry pe;
120	status_t err;
121	// vtophys is called for the start of any page aligned contiguous large buffer,
122	// and also with offset 2 into 2048 byte aligned (non-contiguous) rx/tx buffer.
123	// Thus we only ask for 2046 bytes to get exactly one physical_entry. If the
124	// next physical page is non-contiguous, using 2048 may return B_BUFFER_OVERFLOW.
125	err = get_memory_map((void *)virtual_addr, 2046, &pe, 1);
126	if (err < 0)
127		panic("ipro1000: get_memory_map failed for %p, error %08lx\n", (void *)virtual_addr, err);
128	return pe.address;
129}
130
131#define M_DEVBUF 1
132#define M_NOWAIT 2
133#define PAGE_SIZE 4096
134
135
136struct callout_handle
137{
138	timer_id timer;
139};
140
141void callout_handle_init(struct callout_handle *handle);
142struct callout_handle timeout(timer_function func, void *cookie, bigtime_t timeout);
143void untimeout(timer_function func, void *cookie, struct callout_handle handle);
144
145
146// resource management
147struct resource * bus_alloc_resource(device_t dev, int type, int *rid, int d, int e, int f, int g);
148void bus_release_resource(device_t dev, int type, int reg, struct resource *res);
149uint32 rman_get_start(struct resource *res);
150
151#define	bus_generic_detach(dev)
152
153#define SYS_RES_IOPORT	0x01
154#define SYS_RES_MEMORY	0x02
155#define SYS_RES_IRQ		0x04
156#define RF_SHAREABLE 0
157#define RF_ACTIVE 0
158
159
160#define INTR_TYPE_NET 0
161int bus_setup_intr(device_t dev, struct resource *res, int p3, interrupt_handler int_func, void *cookie, void **tag);
162void bus_teardown_intr(device_t dev, struct resource *res, void *tag);
163
164
165#undef malloc
166#define malloc driver_malloc
167#undef free
168#define free driver_free
169
170void *driver_malloc(int size, int p2, int p3);
171void  driver_free(void *p, int p2);
172
173/* GCC will always emit a read opcode when reading from */
174/* a volatile pointer, even if the result is unused */
175#define E1000_WRITE_FLUSH(a) \
176	E1000_READ_REG(a, STATUS)
177
178/* Read from an absolute offset in the adapter's memory space */
179#define E1000_READ_OFFSET(hw, offset) \
180	(*(volatile uint32 *)((char *)(((struct em_osdep *)(hw)->back)->dev->regAddr) + offset))
181
182/* Write to an absolute offset in the adapter's memory space */
183#define E1000_WRITE_OFFSET(hw, offset, value) \
184	(*(volatile uint32 *)((char *)(((struct em_osdep *)(hw)->back)->dev->regAddr) + offset) = value)
185
186/* Convert a register name to its offset in the adapter's memory space */
187#define E1000_REG_OFFSET(hw, reg) \
188    ((hw)->mac_type >= em_82543 ? E1000_##reg : E1000_82542_##reg)
189
190#define E1000_READ_REG(hw, reg) \
191    E1000_READ_OFFSET(hw, E1000_REG_OFFSET(hw, reg))
192
193#define E1000_WRITE_REG(hw, reg, value) \
194    E1000_WRITE_OFFSET(hw, E1000_REG_OFFSET(hw, reg), value)
195
196#define E1000_READ_REG_ARRAY(hw, reg, index) \
197    E1000_READ_OFFSET(hw, E1000_REG_OFFSET(hw, reg) + ((index) << 2))
198
199#define E1000_WRITE_REG_ARRAY(hw, reg, index, value) \
200    E1000_WRITE_OFFSET(hw, E1000_REG_OFFSET(hw, reg) + ((index) << 2), value)
201
202#define TAILQ_HEAD(name, type) \
203	struct name { struct type *tqh_first, **tqh_last; }
204
205#define TAILQ_ENTRY(type) \
206	struct { struct type *tqe_next, **tqe_prev; }
207
208#define TAILQ_FIRST(head) \
209	((head)->tqh_first)
210
211#define TAILQ_NEXT(elm, field) \
212	((elm)->field.tqe_next)
213
214#define TAILQ_FOREACH(var, head, field) \
215	for ((var) = TAILQ_FIRST((head)); (var); (var) = TAILQ_NEXT((var), field))
216
217#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
218	for ((var) = TAILQ_FIRST((head)); \
219		(var) && ((tvar) = TAILQ_NEXT((var), field), 1); (var) = (tvar))
220
221#define TAILQ_INIT(head) do { \
222	TAILQ_FIRST((head)) = NULL; \
223	(head)->tqh_last = &TAILQ_FIRST((head)); \
224} while (0)
225
226#define TAILQ_INSERT_HEAD(head, elm, field) do { \
227	if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
228		TAILQ_FIRST((head))->field.tqe_prev = &TAILQ_NEXT((elm), field); \
229	else \
230		(head)->tqh_last = &TAILQ_NEXT((elm), field); \
231	TAILQ_FIRST((head)) = (elm); \
232	(elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
233} while (0)
234
235#define TAILQ_REMOVE(head, elm, field) do { \
236	if ((TAILQ_NEXT((elm), field)) != NULL) \
237		TAILQ_NEXT((elm), field)->field.tqe_prev = (elm)->field.tqe_prev; \
238	else \
239		(head)->tqh_last = (elm)->field.tqe_prev; \
240	*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
241} while (0)
242
243#endif
244