source: mainline/uspace/srv/hw/netif/dp8390/ne2000.c@ 37f0a29

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 37f0a29 was 37f0a29, checked in by Martin Decky <martin@…>, 15 years ago

cleanup

  • Property mode set to 100644
File size: 6.5 KB
Line 
1/** @addtogroup ne2k
2 * @{
3 */
4
5/** @file
6 * NE1000 and NE2000 network interface initialization and probe functions implementation.
7 */
8
9#include <stdio.h>
10#include <unistd.h>
11#include "dp8390_port.h"
12#include "dp8390.h"
13#include "ne2000.h"
14
15/** Number of bytes to transfer */
16#define N 100
17
18typedef int (*testf_t)(dpeth_t *dep, int pos, uint8_t *pat);
19
20/** Data patterns */
21uint8_t pat0[] = {0x00, 0x00, 0x00, 0x00};
22uint8_t pat1[] = {0xFF, 0xFF, 0xFF, 0xFF};
23uint8_t pat2[] = {0xA5, 0x5A, 0x69, 0x96};
24uint8_t pat3[] = {0x96, 0x69, 0x5A, 0xA5};
25
26/** Tests 8 bit NE2000 network interface.
27 * @param[in,out] dep The network interface structure.
28 * @param[in] pos The starting position.
29 * @param[in] pat The data pattern to be written.
30 * @returns True on success.
31 * @returns false otherwise.
32 */
33static int test_8(dpeth_t *dep, int pos, uint8_t *pat);
34
35/** Tests 16 bit NE2000 network interface.
36 * @param[in,out] dep The network interface structure.
37 * @param[in] pos The starting position.
38 * @param[in] pat The data pattern to be written.
39 * @returns True on success.
40 * @returns false otherwise.
41 */
42static int test_16(dpeth_t *dep, int pos, uint8_t *pat);
43
44/** Stops the NE2000 network interface.
45 * @param[in,out] dep The network interface structure.
46 */
47static void ne_stop(dpeth_t *dep);
48
49/** Initializes the NE2000 network interface.
50 * @param[in,out] dep The network interface structure.
51 */
52void ne_init(struct dpeth *dep);
53
54int ne_probe(dpeth_t *dep)
55{
56 int byte;
57 int i;
58 int loc1, loc2;
59 testf_t f;
60
61 dep->de_dp8390_port = dep->de_base_port + NE_DP8390;
62
63 /*
64 * We probe for an ne1000 or an ne2000 by testing whether the
65 * on board is reachable through the dp8390. Note that the
66 * ne1000 is an 8bit card and has a memory region distict from
67 * the 16bit ne2000
68 */
69
70 for (dep->de_16bit = 0; dep->de_16bit < 2; dep->de_16bit++) {
71 /* Reset the ethernet card */
72 byte= inb_ne(dep, NE_RESET);
73 usleep(2000);
74 outb_ne(dep, NE_RESET, byte);
75 usleep(2000);
76
77 /* Reset the dp8390 */
78 outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
79 for (i = 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); i++)
80 ; /* Do nothing */
81
82 /* Check if the dp8390 is really there */
83 if ((inb_reg0(dep, DP_CR) & (CR_STP | CR_DM_ABORT)) !=
84 (CR_STP | CR_DM_ABORT))
85 return 0;
86
87 /* Disable the receiver and init TCR and DCR. */
88 outb_reg0(dep, DP_RCR, RCR_MON);
89 outb_reg0(dep, DP_TCR, TCR_NORMAL);
90 if (dep->de_16bit) {
91 outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES |
92 DCR_BMS);
93 } else {
94 outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES |
95 DCR_BMS);
96 }
97
98 if (dep->de_16bit) {
99 loc1= NE2000_START;
100 loc2= NE2000_START + NE2000_SIZE - 4;
101 f= test_16;
102 } else {
103 loc1= NE1000_START;
104 loc2= NE1000_START + NE1000_SIZE - 4;
105 f= test_8;
106 }
107
108 if (f(dep, loc1, pat0) && f(dep, loc1, pat1) &&
109 f(dep, loc1, pat2) && f(dep, loc1, pat3) &&
110 f(dep, loc2, pat0) && f(dep, loc2, pat1) &&
111 f(dep, loc2, pat2) && f(dep, loc2, pat3)) {
112 dep->de_initf = ne_init;
113 dep->de_stopf = ne_stop;
114 return 1;
115 }
116 }
117
118 return 0;
119}
120
121void ne_init(dpeth_t *dep)
122{
123 int i;
124 int word, sendq_nr;
125
126 /* Setup a transfer to get the ethernet address. */
127 if (dep->de_16bit)
128 outb_reg0(dep, DP_RBCR0, 6*2);
129 else
130 outb_reg0(dep, DP_RBCR0, 6);
131
132 outb_reg0(dep, DP_RBCR1, 0);
133 outb_reg0(dep, DP_RSAR0, 0);
134 outb_reg0(dep, DP_RSAR1, 0);
135 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
136
137 for (i = 0; i < 6; i++) {
138 if (dep->de_16bit) {
139 word = inw_ne(dep, NE_DATA);
140 dep->de_address.ea_addr[i] = word;
141 } else
142 dep->de_address.ea_addr[i] = inb_ne(dep, NE_DATA);
143 }
144
145 dep->de_data_port= dep->de_base_port + NE_DATA;
146 if (dep->de_16bit) {
147 dep->de_ramsize = NE2000_SIZE;
148 dep->de_offset_page = NE2000_START / DP_PAGESIZE;
149 } else {
150 dep->de_ramsize = NE1000_SIZE;
151 dep->de_offset_page = NE1000_START / DP_PAGESIZE;
152 }
153
154 /* Allocate one send buffer (1.5KB) per 8KB of on board memory. */
155 sendq_nr = dep->de_ramsize / 0x2000;
156
157 if (sendq_nr < 1)
158 sendq_nr = 1;
159 else if (sendq_nr > SENDQ_NR)
160 sendq_nr = SENDQ_NR;
161
162 dep->de_sendq_nr = sendq_nr;
163 for (i = 0; i < sendq_nr; i++)
164 dep->de_sendq[i].sq_sendpage = dep->de_offset_page + i * SENDQ_PAGES;
165
166 dep->de_startpage = dep->de_offset_page + i * SENDQ_PAGES;
167 dep->de_stoppage = dep->de_offset_page + dep->de_ramsize / DP_PAGESIZE;
168
169 /* Can't override the default IRQ. */
170 dep->de_irq &= ~DEI_DEFAULT;
171
172 printf("%s: Novell NE%d000 ethernet card at I/O address "
173 "%#lx, memory size %#lx, irq %d\n",
174 dep->de_name, dep->de_16bit ? 2 : 1,
175 dep->de_base_port, dep->de_ramsize, dep->de_irq);
176}
177
178static int test_8(dpeth_t *dep, int pos, uint8_t *pat)
179{
180 uint8_t buf[4];
181 int i;
182
183 outb_reg0(dep, DP_ISR, 0xff);
184
185 /* Setup a transfer to put the pattern. */
186 outb_reg0(dep, DP_RBCR0, 4);
187 outb_reg0(dep, DP_RBCR1, 0);
188 outb_reg0(dep, DP_RSAR0, pos & 0xff);
189 outb_reg0(dep, DP_RSAR1, pos >> 8);
190 outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
191
192 for (i = 0; i < 4; i++)
193 outb_ne(dep, NE_DATA, pat[i]);
194
195 for (i = 0; i < N; i++) {
196 if (inb_reg0(dep, DP_ISR) & ISR_RDC)
197 break;
198 }
199
200 if (i == N) {
201 printf("%s: NE1000 remote DMA test failed\n", dep->de_name);
202 return 0;
203 }
204
205 outb_reg0(dep, DP_RBCR0, 4);
206 outb_reg0(dep, DP_RBCR1, 0);
207 outb_reg0(dep, DP_RSAR0, pos & 0xff);
208 outb_reg0(dep, DP_RSAR1, pos >> 8);
209 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
210
211 for (i = 0; i < 4; i++)
212 buf[i] = inb_ne(dep, NE_DATA);
213
214 return (memcmp(buf, pat, 4) == 0);
215}
216
217static int test_16(dpeth_t *dep, int pos, uint8_t *pat)
218{
219 uint8_t buf[4];
220 int i;
221
222 outb_reg0(dep, DP_ISR, 0xff);
223
224 /* Setup a transfer to put the pattern. */
225 outb_reg0(dep, DP_RBCR0, 4);
226 outb_reg0(dep, DP_RBCR1, 0);
227 outb_reg0(dep, DP_RSAR0, pos & 0xff);
228 outb_reg0(dep, DP_RSAR1, pos >> 8);
229 outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
230
231 for (i = 0; i < 4; i += 2)
232 outw_ne(dep, NE_DATA, *(uint16_t *)(pat + i));
233
234 for (i = 0; i < N; i++) {
235 if (inb_reg0(dep, DP_ISR) &ISR_RDC)
236 break;
237 }
238
239 if (i == N) {
240 printf("%s: NE2000 remote DMA test failed\n", dep->de_name);
241 return 0;
242 }
243
244 outb_reg0(dep, DP_RBCR0, 4);
245 outb_reg0(dep, DP_RBCR1, 0);
246 outb_reg0(dep, DP_RSAR0, pos & 0xff);
247 outb_reg0(dep, DP_RSAR1, pos >> 8);
248 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
249
250 for (i = 0; i < 4; i += 2)
251 *(uint16_t *)(buf + i) = inw_ne(dep, NE_DATA);
252
253 return (memcmp(buf, pat, 4) == 0);
254}
255
256static void ne_stop(dpeth_t *dep)
257{
258 /* Reset the ethernet card */
259 int byte = inb_ne(dep, NE_RESET);
260 usleep(2000);
261 outb_ne(dep, NE_RESET, byte);
262}
263
264/** @}
265 */
Note: See TracBrowser for help on using the repository browser.