1 /* $NetBSD: if_ie.c,v 1.12 2008/01/12 09:54:32 tsutsui Exp $ */
4 * Copyright (c) 1995 Theo de Raadt
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 #include <sys/param.h>
29 #include <sys/types.h>
30 #include <sys/socket.h>
32 #include <netinet/in.h>
33 #include <netinet/in_systm.h>
36 #include <net/if_ether.h>
38 #include <lib/libkern/libkern.h>
39 #include <lib/libsa/stand.h>
40 #include <lib/libsa/net.h>
44 #define IE_RBUF_SIZE ETHER_MAX_LEN
46 #include <machine/prom.h>
58 void ie_stop(struct netif
*);
59 void ie_end(struct netif
*);
60 void ie_error(struct netif
*, char *, volatile struct iereg
*);
61 int ie_get(struct iodesc
*, void *, size_t, saseconds_t
);
62 void ie_init(struct iodesc
*, void *);
63 int ie_match(struct netif
*, void *);
64 int ie_poll(struct iodesc
*, void *, int);
65 int ie_probe(struct netif
*, void *);
66 int ie_put(struct iodesc
*, void *, size_t);
67 void ie_reset(struct netif
*, u_char
*);
68 void ieack(volatile struct iereg
*, struct iemem
*);
70 struct netif_stats ie_stats
;
72 struct netif_dif ie0_dif
= {
80 struct netif_driver ie_driver
= {
81 "ie", /* netif_bname */
88 &ie0_dif
, /* netif_ifs */
92 struct ie_configuration
{
99 int nie_config
= __arraycount(ie_config
);
102 struct iereg
*sc_reg
; /* IE registers */
103 struct iemem
*sc_mem
; /* RAM */
107 ie_match(struct netif
*nif
, void *machdep_hint
)
112 if (bugargs
.cputyp
== CPU_147
)
115 if (name
&& !memcmp(ie_driver
.netif_bname
, name
, 2))
117 for (i
= 0; i
< nie_config
; i
++) {
118 if (ie_config
[i
].used
)
121 printf("ie%d: ie_match --> %d\n", i
, val
+ 1);
126 printf("ie%d: ie_match --> 0\n", i
);
131 ie_probe(struct netif
*nif
, void *machdep_hint
)
134 /* the set unit is the current unit */
136 printf("ie%d: ie_probe called\n", nif
->nif_unit
);
138 if (bugargs
.cputyp
!= CPU_147
)
144 ie_error(struct netif
*nif
, char *str
, volatile struct iereg
*ier
)
147 panic("ie%d: unknown error", nif
->nif_unit
);
151 ieack(volatile struct iereg
*ier
, struct iemem
*iem
)
154 /* ack the `interrupt' */
155 iem
->im_scb
.ie_command
= iem
->im_scb
.ie_status
& IE_ST_WHENCE
;
156 ier
->ie_attention
= 1; /* chan attention! */
157 while (iem
->im_scb
.ie_command
)
162 ie_reset(struct netif
*nif
, u_char
*myea
)
164 volatile struct iereg
*ier
= ie_softc
.sc_reg
;
165 struct iemem
*iem
= ie_softc
.sc_mem
;
171 printf("ie%d: ie_reset called\n", nif
->nif_unit
);
173 /*printf("ier %x iem %x\n", ier, iem);*/
175 *(u_char
*)0xfff4202a = 0x40;
177 memset(iem
, 0, sizeof(*iem
));
178 iem
->im_scp
.scp_sysbus
= 0;
179 iem
->im_scp
.scp_iscp_low
= (int)&iem
->im_iscp
& 0xffff;
180 iem
->im_scp
.scp_iscp_high
= (int)&iem
->im_iscp
>> 16;
182 iem
->im_iscp
.iscp_scboffset
= (int)&iem
->im_scb
- (int) iem
;
183 iem
->im_iscp
.iscp_busy
= 1;
184 iem
->im_iscp
.iscp_base_low
= (int)iem
& 0xffff;
185 iem
->im_iscp
.iscp_base_high
= (int)iem
>> 16;
188 * completely and utterly unlike what i expected, the
190 * 1st: d15-d0 -> high address
191 * 2nd: d31-d16 -> low address
196 ier
->ie_porthigh
= a
& 0xffff;
199 ier
->ie_portlow
= a
>> 16;
203 /* set new SCP pointer */
204 a
= (int) &iem
->im_scp
| IE_PORT_NEWSCP
;
205 ier
->ie_porthigh
= a
& 0xffff;
208 ier
->ie_portlow
= a
>> 16;
212 ier
->ie_attention
= 1; /* chan attention! */
213 for (t
= timo
* 10; t
--;)
216 /* send CONFIGURE command */
217 iem
->im_scb
.ie_command
= IE_CU_START
;
218 iem
->im_scb
.ie_command_list
= (int) &iem
->im_cc
- (int) iem
;
219 iem
->im_cc
.com
.ie_cmd_status
= 0;
220 iem
->im_cc
.com
.ie_cmd_cmd
= IE_CMD_CONFIG
| IE_CMD_LAST
;
221 iem
->im_cc
.com
.ie_cmd_link
= 0xffff;
222 iem
->im_cc
.ie_config_count
= 0x0c;
223 iem
->im_cc
.ie_fifo
= 8;
224 iem
->im_cc
.ie_save_bad
= 0x40;
225 iem
->im_cc
.ie_addr_len
= 0x2e;
226 iem
->im_cc
.ie_priority
= 0;
227 iem
->im_cc
.ie_ifs
= 0x60;
228 iem
->im_cc
.ie_slot_low
= 0;
229 iem
->im_cc
.ie_slot_high
= 0xf2;
230 iem
->im_cc
.ie_promisc
= 0;
231 iem
->im_cc
.ie_crs_cdt
= 0;
232 iem
->im_cc
.ie_min_len
= 64;
233 iem
->im_cc
.ie_junk
= 0xff;
235 ier
->ie_attention
= 1; /* chan attention! */
236 for (t
= timo
* 10; t
--;)
241 /*printf("ic %x\n", &iem->im_ic);*/
242 /* send IASETUP command */
243 iem
->im_scb
.ie_command
= IE_CU_START
;
244 iem
->im_scb
.ie_command_list
= (int)&iem
->im_ic
- (int)iem
;
245 iem
->im_ic
.com
.ie_cmd_status
= 0;
246 iem
->im_ic
.com
.ie_cmd_cmd
= IE_CMD_IASETUP
| IE_CMD_LAST
;
247 iem
->im_ic
.com
.ie_cmd_link
= 0xffff;
248 memcpy((void *)&iem
->im_ic
.ie_address
, myea
,
249 sizeof(iem
->im_ic
.ie_address
));
251 ier
->ie_attention
= 1; /* chan attention! */
252 for (t
= timo
* 10; t
--;)
259 for (i
= 0; i
< NRXBUF
; i
++) {
260 iem
->im_rfd
[i
].ie_fd_next
= (int)&iem
->im_rfd
[(i
+1) % NRXBUF
] -
262 iem
->im_rbd
[i
].ie_rbd_next
= (int)&iem
->im_rbd
[(i
+1) % NRXBUF
] -
264 a
= (int)&iem
->im_rxbuf
[i
* IE_RBUF_SIZE
];
265 iem
->im_rbd
[i
].ie_rbd_buffer_low
= a
& 0xffff;
266 iem
->im_rbd
[i
].ie_rbd_buffer_high
= a
>> 16;
267 iem
->im_rbd
[i
].ie_rbd_length
= IE_RBUF_SIZE
;
269 iem
->im_rfd
[NRXBUF
- 1].ie_fd_last
|= IE_FD_LAST
;
270 iem
->im_rbd
[NRXBUF
- 1].ie_rbd_length
|= IE_RBD_LAST
;
271 iem
->im_rfd
[0].ie_fd_buf_desc
= (int)&iem
->im_rbd
[0] - (int)iem
;
274 printf("rfd[0] %x rbd[0] %x buf[0] %x\n", &iem
->im_rfd
, &iem
->im_rbd
,
278 /* send receiver start command */
279 iem
->im_scb
.ie_command
= IE_RU_START
;
280 iem
->im_scb
.ie_command_list
= 0;
281 iem
->im_scb
.ie_recv_list
= (int) &iem
->im_rfd
[0] - (int) iem
;
282 ier
->ie_attention
= 1; /* chan attention! */
283 while (iem
->im_scb
.ie_command
)
290 ie_poll(struct iodesc
*desc
, void *pkt
, int len
)
292 volatile struct iereg
*ier
= ie_softc
.sc_reg
;
293 struct iemem
*iem
= ie_softc
.sc_mem
;
298 __asm(".word 0xf518\n");
299 status
= iem
->im_rfd
[slot
].ie_fd_status
;
300 if (status
& IE_FD_BUSY
)
303 /* printf("slot %d: %x\n", slot, status); */
304 if ((status
& (IE_FD_COMPLETE
| IE_FD_OK
)) ==
305 (IE_FD_COMPLETE
| IE_FD_OK
)) {
306 if (status
& IE_FD_OK
) {
307 length
= iem
->im_rbd
[slot
].ie_rbd_actual
& 0x3fff;
310 memcpy(pkt
, (void *)&iem
->im_rxbuf
[slot
* IE_RBUF_SIZE
],
313 iem
->im_rfd
[slot
].ie_fd_status
= 0;
314 iem
->im_rfd
[slot
].ie_fd_last
|= IE_FD_LAST
;
315 iem
->im_rfd
[(slot
+NRXBUF
-1)%NRXBUF
].ie_fd_last
&=
317 iem
->im_rbd
[slot
].ie_rbd_actual
= 0;
318 iem
->im_rbd
[slot
].ie_rbd_length
|= IE_RBD_LAST
;
319 iem
->im_rbd
[(slot
+NRXBUF
-1)%NRXBUF
].ie_rbd_length
&=
322 printf("S%d\n", slot
);
328 /* should move descriptor onto end of queue... */
330 if ((iem
->im_scb
.ie_status
& IE_RU_READY
) == 0) {
333 for (slot
= 0; slot
< NRXBUF
; slot
++) {
334 iem
->im_rbd
[slot
].ie_rbd_length
&= ~IE_RBD_LAST
;
335 iem
->im_rfd
[slot
].ie_fd_last
&= ~IE_FD_LAST
;
337 iem
->im_rbd
[NRXBUF
-1].ie_rbd_length
|= IE_RBD_LAST
;
338 iem
->im_rfd
[NRXBUF
-1].ie_fd_last
|= IE_FD_LAST
;
340 iem
->im_rfd
[0].ie_fd_buf_desc
= (int)&iem
->im_rbd
[0] - (int)iem
;
342 iem
->im_scb
.ie_command
= IE_RU_START
;
343 iem
->im_scb
.ie_command_list
= 0;
344 iem
->im_scb
.ie_recv_list
= (int)&iem
->im_rfd
[0] - (int)iem
;
345 ier
->ie_attention
= 1; /* chan attention! */
346 while (iem
->im_scb
.ie_command
)
350 slot
= slot
% NRXBUF
;
355 ie_put(struct iodesc
*desc
, void *pkt
, size_t len
)
357 volatile struct iereg
*ier
= ie_softc
.sc_reg
;
358 struct iemem
*iem
= ie_softc
.sc_mem
;
363 /* send transmit command */
365 while (iem
->im_scb
.ie_command
)
369 memcpy((void *)&iem
->im_txbuf
[xx
], p
, len
);
371 len
= MAX(len
, ETHER_MIN_LEN
);
373 /* build transmit descriptor */
374 iem
->im_xd
[xx
].ie_xmit_flags
= len
| IE_XMIT_LAST
;
375 iem
->im_xd
[xx
].ie_xmit_next
= 0xffff;
376 a
= (int) &iem
->im_txbuf
[xx
];
377 iem
->im_xd
[xx
].ie_xmit_buf_low
= a
& 0xffff;
378 iem
->im_xd
[xx
].ie_xmit_buf_high
= a
>> 16;
380 /* transmit command */
381 iem
->im_xc
[xx
].com
.ie_cmd_status
= 0;
382 iem
->im_xc
[xx
].com
.ie_cmd_cmd
= IE_CMD_XMIT
| IE_CMD_LAST
;
383 iem
->im_xc
[xx
].com
.ie_cmd_link
= 0xffff;
384 iem
->im_xc
[xx
].ie_xmit_desc
= (int)&iem
->im_xd
[xx
] - (int)iem
;
385 iem
->im_xc
[xx
].ie_xmit_length
= len
;
386 memcpy((void *)&iem
->im_xc
[xx
].ie_xmit_addr
, p
,
387 sizeof iem
->im_xc
[xx
].ie_xmit_addr
);
389 iem
->im_scb
.ie_command
= IE_CU_START
;
390 iem
->im_scb
.ie_command_list
= (int)&iem
->im_xc
[xx
] - (int)iem
;
392 ier
->ie_attention
= 1; /* chan attention! */
395 printf("ie%d: send %d to %x:%x:%x:%x:%x:%x\n",
396 ((struct netif
*)desc
->io_netif
)->nif_unit
, len
,
397 p
[0], p
[1], p
[2], p
[3], p
[4], p
[5]);
403 ie_get(struct iodesc
*desc
, void *pkt
, size_t len
, saseconds_t timeout
)
410 while (((getsecs() - t
) < timeout
) && !cc
) {
411 cc
= ie_poll(desc
, pkt
, len
);
416 * init ie device. return 0 on failure, 1 if ok.
419 ie_init(struct iodesc
*desc
, void *machdep_hint
)
421 struct netif
*nif
= desc
->io_netif
;
424 printf("ie%d: ie_init called\n", nif
->nif_unit
);
425 machdep_common_ether(desc
->myea
);
426 memset(&ie_softc
, 0, sizeof(ie_softc
));
428 (struct iereg
*)ie_config
[nif
->nif_unit
].phys_addr
;
429 ie_softc
.sc_mem
= (struct iemem
*)0x3e0000;
430 ie_reset(desc
->io_netif
, desc
->myea
);
431 printf("device: %s%d attached to %s\n", nif
->nif_driver
->netif_bname
,
432 nif
->nif_unit
, ether_sprintf(desc
->myea
));
436 ie_stop(struct netif
*nif
)
438 volatile struct iereg
*ier
= ie_softc
.sc_reg
;
439 struct iemem
*iem
= ie_softc
.sc_mem
;
444 iem
->im_iscp
.iscp_busy
= 1;
447 ier
->ie_porthigh
= a
& 0xffff;
450 ier
->ie_portlow
= a
>> 16;
454 /* reset chip again */
456 ier
->ie_porthigh
= a
& 0xffff;
459 ier
->ie_portlow
= a
>> 16;
464 printf("status %x busy %x\n", iem
->im_scb
.ie_status
,
465 iem
->im_iscp
.iscp_busy
);
470 ie_end(struct netif
*nif
)
474 printf("ie%d: ie_end called\n", nif
->nif_unit
);
479 *(u_char
*)0xfff42002 = 0;