1/*
2 * CFE OS Independent Layer
3 *
4 * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 * $Id: cfe_osl.c 419467 2013-08-21 09:19:48Z $
19 */
20
21#include <typedefs.h>
22#include <bcmdefs.h>
23#include <osl.h>
24#include <bcmutils.h>
25
26/* Global ASSERT type */
27uint32 g_assert_type = 0;
28
29osl_t *
30osl_attach(void *pdev)
31{
32	osl_t *osh;
33
34	osh = (osl_t *)KMALLOC(sizeof(osl_t), 0);
35	ASSERT(osh);
36
37	bzero(osh, sizeof(osl_t));
38	osh->pdev = pdev;
39	return osh;
40}
41
42void
43osl_detach(osl_t *osh)
44{
45	if (osh == NULL)
46		return;
47	KFREE((void*) KERNADDR(PHYSADDR((ulong)osh)));
48}
49
50struct lbuf *
51osl_pktget(uint len)
52{
53	uchar *buf;
54	struct lbuf *lb;
55
56	ASSERT(len <= LBDATASZ);
57
58	if (!(buf = KMALLOC(LBUFSZ, 0)))
59		return NULL;
60
61	lb = (struct lbuf *) &buf[LBDATASZ];
62	bzero(lb, sizeof(struct lbuf));
63	lb->head = lb->data = buf;
64	lb->end = buf + len;
65	lb->len = len;
66	lb->tail = lb->data + len;
67	return lb;
68}
69
70void
71osl_pktfree(osl_t *osh, struct lbuf *lb, bool send)
72{
73	struct lbuf *next;
74
75	if (send && osh->tx_fn)
76		osh->tx_fn(osh->tx_ctx, lb, 0);
77
78	for (; lb; lb = next) {
79		ASSERT(!lb->link);
80		next = lb->next;
81		KFREE((void *) KERNADDR(PHYSADDR((ulong) lb->head)));
82	}
83}
84
85struct lbuf *
86osl_pktdup(struct lbuf *lb)
87{
88	struct lbuf *dup;
89
90	if (!(dup = osl_pktget(lb->len)))
91		return NULL;
92
93	bcopy(lb->data, dup->data, lb->len);
94	ASSERT(!lb->link);
95	return dup;
96}
97
98void
99osl_pktsetlen(struct lbuf *lb, uint len)
100{
101	ASSERT((lb->data + len) <= lb->end);
102
103	lb->len = len;
104	lb->tail = lb->data + len;
105}
106
107uchar *
108osl_pktpush(struct lbuf *lb, uint bytes)
109{
110	ASSERT((lb->data - bytes) >= lb->head);
111
112	lb->data -= bytes;
113	lb->len += bytes;
114
115	return lb->data;
116}
117
118uchar *
119osl_pktpull(struct lbuf *lb, uint bytes)
120{
121	ASSERT((lb->data + bytes) <= lb->end);
122	ASSERT(lb->len >= bytes);
123
124	lb->data += bytes;
125	lb->len -= bytes;
126
127	return lb->data;
128}
129
130void *
131osl_dma_alloc_consistent(uint size, uint16 align_bits, uint *alloced, ulong *pap)
132{
133	void *buf;
134	uint16 align = (1 << align_bits);
135
136	/* fix up the alignment requirements first */
137	if (!ISALIGNED(DMA_CONSISTENT_ALIGN, align))
138		size += align;
139	*alloced = size;
140
141	if (!(buf = KMALLOC(size, DMA_CONSISTENT_ALIGN)))
142		return NULL;
143
144	*((ulong *) pap) = PHYSADDR((ulong) buf);
145
146	cfe_flushcache(CFE_CACHE_FLUSH_D);
147
148	return (void *) UNCADDR((ulong) buf);
149}
150
151void
152osl_dma_free_consistent(void *va)
153{
154	KFREE((void *) KERNADDR(PHYSADDR((ulong) va)));
155}
156
157
158int
159osl_busprobe(uint32 *val, uint32 addr)
160{
161	*val = R_REG(NULL, (volatile uint32 *) addr);
162
163	return 0;
164}
165
166/* translate bcmerros */
167int
168osl_error(int bcmerror)
169{
170	if (bcmerror)
171		return -1;
172	else
173		return 0;
174}
175
176/* Converts a OS packet to driver packet.
177 * The original packet data is copied to the new driver packet
178 */
179void
180osl_pkt_frmnative(iocb_buffer_t *buffer, struct lbuf *lb)
181{
182	bcopy(buffer->buf_ptr, PKTDATA(NULL, lb), buffer->buf_length);
183}
184
185/* Converts a driver packet into OS packet.
186 * The data is copied to the OS packet
187 */
188void
189osl_pkt_tonative(struct lbuf* lb, iocb_buffer_t *buffer)
190{
191	bcopy(PKTDATA(NULL, lb), buffer->buf_ptr, PKTLEN(NULL, lb));
192	buffer->buf_retlen = PKTLEN(NULL, lb);
193
194	/* RFC894: Minimum length of IP over Ethernet packet is 46 octets */
195	if (buffer->buf_retlen < 60) {
196		bzero(buffer->buf_ptr + buffer->buf_retlen, 60 - buffer->buf_retlen);
197		buffer->buf_retlen = 60;
198	}
199}
200