1 /* $Id: ptifddi.c,v 1.7 1999/06/09 08:19:01 davem Exp $
2 * ptifddi.c: Network driver for Performance Technologies single-attach
3 * and dual-attach FDDI sbus cards.
5 * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
9 "ptifddi.c:v1.0 10/Dec/96 David S. Miller (davem@caipfs.rutgers.edu)\n";
11 #include <linux/string.h>
12 #include <linux/init.h>
16 #include "ptifddi_asm.h"
19 static struct ptifddi
*root_pti_dev
= NULL
;
22 static inline void pti_reset(struct ptifddi
*pp
)
27 static inline void pti_unreset(struct ptifddi
*pp
)
32 static inline void pti_load_code_base(struct dfddi_ram
*rp
, unsigned short addr
)
34 rp
->loader_addr
= ((addr
<< 8) & 0xff00) | ((addr
>> 8) & 0x00ff);
37 static inline void pti_clear_dpram(struct ptifddi
*pp
)
39 memset(pp
->dpram
, 0, DPRAM_SIZE
);
42 #define CARD_TEST_TIMEOUT 100000
44 static inline int pti_card_test(struct ptifddi
*pp
)
46 struct dfddi_ram
*rp
= pp
->dpram
;
47 unsigned char *code
= &rp
->loader
;
48 unsigned char *status
= (unsigned char *) rp
;
49 int clicks
= CARD_TEST_TIMEOUT
;
55 for(i
= 0; i
< test_firmware_size
; i
++)
56 code
[i
] = test_firmware
[i
];
58 /* Tell card where to execute the code. */
59 pti_load_code_base(pp
, test_firmware_dev_addr
);
61 /* Clear test run status in dpram. */
64 /* Reset single attach state machine before the test. */
67 /* Unreset, to get the test code running. */
70 /* Wait for dpram status to become 5, else fail if we time out. */
81 static inline void pti_init_firmware_loader(struct ptifddi
*pp
)
83 struct dfddi_ram
*rp
= pp
->dpram
;
86 for(i
= 0; i
< firmware_loader_size
; i
++)
87 rp
->loader
.loader_firmware
[i
] = firmware_loader
[i
];
90 static inline void pti_load_main_firmware(struct ptifddi
*pp
)
92 struct dfddi_ram
*rp
= pp
->dpram
;
93 struct dpram_loader
*lp
= &rp
.loader
;
99 static void pti_init_rings(struct ptifddi
*pp
, int from_irq
)
103 static int pti_init(struct ptifddi
*pp
, int from_irq
)
107 static void pti_is_not_so_happy(struct ptifddi
*pp
)
111 static inline void pti_tx(struct ptifddi
*pp
, struct device
*dev
)
115 static inline void myri_rx(struct ptifddi
*pp
, struct device
*dev
)
119 static void pti_interrupt(int irq
, void *dev_id
, struct pt_regs
*regs
)
121 struct device
*dev
= (struct device
*) dev_id
;
122 struct ptifddi
*pp
= (struct ptifddi
*) dev
->priv
;
126 static int pti_open(struct device
*dev
)
128 struct ptifddi
*pp
= (struct ptifddi
*) dev
->priv
;
130 return pti_init(pp
, in_interrupt());
133 static int pti_close(struct device
*dev
)
135 struct ptifddi
*pp
= (struct ptifddi
*) dev
->priv
;
140 static int pti_start_xmit(struct sk_buff
*skb
, struct device
*dev
)
142 struct ptifddi
*pp
= (struct ptifddi
*) dev
->priv
;
145 static struct enet_statistics
*pti_get_stats(struct device
*dev
)
146 { return &(((struct ptifddi
*)dev
->priv
)->enet_stats
); }
148 static void pti_set_multicast(struct device
*dev
)
152 static inline int pti_fddi_init(struct device
*dev
, struct linux_sbus_device
*sdev
, int num
)
154 static unsigned version_printed
= 0;
158 dev
= init_fddidev(0, sizeof(struct ptifddi
));
160 if(version_printed
++ == 0)
163 prom_apply_sbus_ranges(sdev
->my_bus
, &sdev
->reg_addrs
[0],
164 sdev
->num_registers
, sdev
);
166 /* Register 0 mapping contains DPRAM. */
167 pp
->dpram
= sparc_alloc_io(sdev
->reg_addrs
[0].phys_addr
, 0,
168 sdev
->reg_addrs
[0].reg_size
,
170 sdev
->reg_addrs
[0].which_io
, 0);
172 printk("ptiFDDI: Cannot map DPRAM I/O area.\n");
176 /* Next, register 1 contains reset byte. */
177 pp
->reset
= sparc_alloc_io(sdev
->reg_addrs
[1].phys_addr
, 0,
178 sdev
->reg_addrs
[1].reg_size
,
179 "PTI FDDI RESET Byte",
180 sdev
->reg_addrs
[1].which_io
, 0);
182 printk("ptiFDDI: Cannot map RESET byte.\n");
186 /* Register 2 contains unreset byte. */
187 pp
->unreset
= sparc_alloc_io(sdev
->reg_addrs
[2].phys_addr
, 0,
188 sdev
->reg_addrs
[2].reg_size
,
189 "PTI FDDI UNRESET Byte",
190 sdev
->reg_addrs
[2].which_io
, 0);
192 printk("ptiFDDI: Cannot map UNRESET byte.\n");
196 /* Reset the card. */
199 /* Run boot-up card tests. */
200 i
= pti_card_test(pp
);
202 printk("ptiFDDI: Bootup card test fails.\n");
206 /* Clear DPRAM, start afresh. */
209 /* Init the firmware loader. */
210 pti_init_firmware_loader(pp
);
212 /* Now load main card FDDI firmware, using the loader. */
213 pti_load_main_firmware(pp
);
216 int __init
ptifddi_sbus_probe(struct device
*dev
)
218 struct linux_sbus
*bus
;
219 struct linux_sbus_device
*sdev
= 0;
220 static int called
= 0;
228 for_each_sbusdev(sdev
, bus
) {
229 if(cards
) dev
= NULL
;
230 if(!strcmp(sdev
->prom_name
, "PTI,sbs600") ||
231 !strcmp(sdev
->prom_name
, "DPV,fddid")) {
233 DET(("Found PTI FDDI as %s\n", sdev
->prom_name
));
234 if((v
= pti_fddi_init(dev
, sdev
, (cards
- 1))))
251 return ptifddi_sbus_probe(NULL
);
259 /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
260 while (root_pti_dev
) {
261 pp
= root_pti_dev
->next_module
;
263 unregister_netdev(root_pti_dev
->dev
);
264 kfree(root_pti_dev
->dev
);