1 /**************************************************************************
2 Etherboot - BOOTP/TFTP Bootstrap Program
4 TIARA (Fujitsu Etherstar) NIC driver for Etherboot
5 Copyright (c) Ken Yap 1998
7 Information gleaned from:
9 TIARA.ASM Packet driver by Brian Fisher, Queens U, Kingston, Ontario
10 Fujitsu MB86960 spec sheet (different chip but same family)
11 ***************************************************************************/
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License as
16 * published by the Free Software Foundation; either version 2, or (at
17 * your option) any later version.
20 /* to get some global routines like printf */
21 #include "etherboot.h"
22 /* to get the interface to the body of the program */
27 EtherStar I/O Register offsets
30 /* Offsets of registers */
31 #define DLCR_XMIT_STAT 0x00
32 #define DLCR_XMIT_MASK 0x01
33 #define DLCR_RECV_STAT 0x02
34 #define DLCR_RECV_MASK 0x03
35 #define DLCR_XMIT_MODE 0x04
36 #define DLCR_RECV_MODE 0x05
37 #define DLCR_ENABLE 0x06
38 #define DLCR_TDR_LOW 0x07
39 #define DLCR_NODE_ID 0x08
40 #define DLCR_TDR_HIGH 0x0F
41 #define BMPR_MEM_PORT 0x10
42 #define BMPR_PKT_LEN 0x12
43 #define BMPR_DMA_ENABLE 0x14
48 #define TMT_16COLL 0x02
49 #define BUF_EMPTY 0x40
51 #define CARD_DISABLE 0x80 /* written to DLCR_ENABLE to disable card */
52 #define CARD_ENABLE 0 /* written to DLCR_ENABLE to enable card */
54 #define CLEAR_STATUS 0x0F /* used to clear status info */
58 !!!!!!!+--------CLEAR BUS WRITE ERROR
59 !!!!!!+---------CLEAR 16 COLLISION
60 !!!!!+----------CLEAR COLLISION
61 !!!!+-----------CLEAR UNDERFLOW
68 #define NO_TX_IRQS 0 /* written to clear transmit IRQs */
70 #define CLR_RCV_STATUS 0xCF /* clears receive status */
72 #define EN_RCV_IRQS 0x80 /* enable receive interrupts */
76 !!!!!!!+--------ENABLE OVERFLOW
77 !!!!!!+---------ENABLE CRC
78 !!!!!+----------ENABLE ALIGN
79 !!!!+-----------ENABLE SHORT PKT
80 !!!+------------DISABLE REMOTE RESET
81 !!+-------------RESERVED
82 !+--------------RESERVED
83 +---------------ENABLE PKT READY
86 #define XMIT_MODE 0x02
89 !!!!!!!!---------ENABLE CARRIER DETECT
90 !!!!!!!+---------DISABLE LOOPBACK
93 #define RECV_MODE 0x02
96 !!!!!!!!---------ACCEPT ALL PACKETS
97 !!!!!!!+---------ACCEPT PHYSICAL, MULTICAST, AND
98 !!!!!!+----------BROADCAST PACKETS
99 !!!!!+-----------DISABLE REMOTE RESET
100 !!!!+------------DISABLE SHORT PACKETS
101 !!!+-------------USE 6 BYTE ADDRESS
104 +----------------DISABLE CRC TEST MODE
107 /* NIC specific static variables go here */
109 static unsigned short ioaddr
;
111 /**************************************************************************
112 RESET - Reset adapter
113 ***************************************************************************/
114 static void tiara_reset(struct nic
*nic
)
118 outb(CARD_DISABLE
, ioaddr
+ DLCR_ENABLE
);
119 outb(CLEAR_STATUS
, ioaddr
+ DLCR_XMIT_STAT
);
120 outb(NO_TX_IRQS
, ioaddr
+ DLCR_XMIT_MASK
);
121 outb(CLR_RCV_STATUS
, ioaddr
+ DLCR_RECV_STAT
);
122 outb(XMIT_MODE
, ioaddr
+ DLCR_XMIT_MODE
);
123 outb(RECV_MODE
, ioaddr
+ DLCR_RECV_MODE
);
124 /* Vacuum recv buffer */
125 while ((inb(ioaddr
+ DLCR_RECV_MODE
) & BUF_EMPTY
) == 0)
126 inb(ioaddr
+ BMPR_MEM_PORT
);
127 /* Set node address */
128 for (i
= 0; i
< ETH_ALEN
; ++i
)
129 outb(nic
->node_addr
[i
], ioaddr
+ DLCR_NODE_ID
+ i
);
130 outb(CLR_RCV_STATUS
, ioaddr
+ DLCR_RECV_STAT
);
131 outb(CARD_ENABLE
, ioaddr
+ DLCR_ENABLE
);
134 /**************************************************************************
135 POLL - Wait for a frame
136 ***************************************************************************/
137 static int tiara_poll(struct nic
*nic
)
141 if (inb(ioaddr
+ DLCR_RECV_MODE
) & BUF_EMPTY
)
144 outw(CLR_RCV_STATUS
, ioaddr
+ DLCR_RECV_STAT
);
145 len
= inw(ioaddr
+ BMPR_MEM_PORT
); /* throw away status */
146 len
= inw(ioaddr
+ BMPR_MEM_PORT
);
147 /* Drop overlength packets */
148 if (len
> ETH_FRAME_LEN
)
149 return (0); /* should we drain the buffer? */
150 insw(ioaddr
+ BMPR_MEM_PORT
, nic
->packet
, len
/ 2);
151 /* If it's our own, drop it */
152 if (memcmp(nic
->packet
+ ETH_ALEN
, nic
->node_addr
, ETH_ALEN
) == 0)
154 nic
->packetlen
= len
;
158 /**************************************************************************
159 TRANSMIT - Transmit a frame
160 ***************************************************************************/
161 static void tiara_transmit(
163 const char *d
, /* Destination */
164 unsigned int t
, /* Type */
165 unsigned int s
, /* size */
166 const char *p
) /* Packet */
175 outsw(ioaddr
+ BMPR_MEM_PORT
, d
, ETH_ALEN
/ 2);
176 outsw(ioaddr
+ BMPR_MEM_PORT
, nic
->node_addr
, ETH_ALEN
/ 2);
177 outw(t
, ioaddr
+ BMPR_MEM_PORT
);
178 outsw(ioaddr
+ BMPR_MEM_PORT
, p
, s
/ 2);
179 if (s
& 1) /* last byte */
180 outb(p
[s
-1], ioaddr
+ BMPR_MEM_PORT
);
181 while (s
++ < ETH_ZLEN
- ETH_HLEN
) /* pad */
182 outb(0, ioaddr
+ BMPR_MEM_PORT
);
183 outw(len
| (TMST
<< 8), ioaddr
+ BMPR_PKT_LEN
);
184 /* wait for transmit complete */
185 time
= currticks() + TICKS_PER_SEC
; /* wait one second */
186 while (currticks() < time
&& (inb(ioaddr
) & (TMT_OK
|TMT_16COLL
)) == 0)
188 if ((inb(ioaddr
) & (TMT_OK
|TMT_16COLL
)) == 0)
189 printf("Tiara timed out on transmit\n");
190 /* Do we need to ack the transmit? */
193 /**************************************************************************
194 DISABLE - Turn off ethernet interface
195 ***************************************************************************/
196 static void tiara_disable(struct nic
*nic
)
198 /* Apparently only a power down can do this properly */
199 outb(CARD_DISABLE
, ioaddr
+ DLCR_ENABLE
);
202 static int tiara_probe1(struct nic
*nic
)
204 /* Hope all the Tiara cards have this vendor prefix */
205 static char vendor_prefix
[] = { 0x08, 0x00, 0x1A };
206 static char all_ones
[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
209 for (i
= 0; i
< ETH_ALEN
; ++i
)
210 nic
->node_addr
[i
] = inb(ioaddr
+ PROM_ID
+ i
);
211 if (memcmp(nic
->node_addr
, vendor_prefix
, sizeof(vendor_prefix
)) != 0)
213 if (memcmp(nic
->node_addr
, all_ones
, sizeof(all_ones
)) == 0)
215 printf("\nTiara ioaddr %#hX, addr %!\n", ioaddr
, nic
->node_addr
);
219 /**************************************************************************
220 PROBE - Look for an adapter, this routine's visible to the outside
221 ***************************************************************************/
222 struct nic
*tiara_probe(struct nic
*nic
, unsigned short *probe_addrs
)
224 /* missing entries are addresses usually already used */
225 static unsigned short io_addrs
[] = {
226 0x100, 0x120, 0x140, 0x160,
227 0x180, 0x1A0, 0x1C0, 0x1E0,
228 0x200, 0x220, 0x240, /*Par*/
229 0x280, 0x2A0, 0x2C0, /*Ser*/
230 0x300, 0x320, 0x340, /*Par*/
231 0x380, /*Vid,Par*/ 0x3C0, /*Ser*/
236 /* if probe_addrs is 0, then routine can use a hardwired default */
237 if (probe_addrs
== 0)
238 probe_addrs
= io_addrs
;
239 for (p
= probe_addrs
; (ioaddr
= *p
) != 0; ++p
)
240 if (tiara_probe1(nic
))
246 /* point to NIC specific routines */
247 nic
->reset
= tiara_reset
;
248 nic
->poll
= tiara_poll
;
249 nic
->transmit
= tiara_transmit
;
250 nic
->disable
= tiara_disable
;