Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Pci/pcmcia code for wavelan.c */
2
 
3
#include "u.h"
4
#include "../port/lib.h"
5
#include "mem.h"
6
#include "dat.h"
7
#include "fns.h"
8
#include "io.h"
9
#include "../port/error.h"
10
#include "../port/netif.h"
11
#include "etherif.h"
12
 
13
#include "wavelan.h"
14
 
15
static int
16
wavelanpcmciareset(Ether *ether)
17
{
18
	int i;
19
	char *p;
20
	Ctlr *ctlr;
21
 
22
	if((ctlr = malloc(sizeof(Ctlr))) == nil)
23
		return -1;
24
 
25
	ilock(ctlr);
26
	ctlr->ctlrno = ether->ctlrno;
27
 
28
	if (ether->port==0)
29
		ether->port=WDfltIOB;
30
	ctlr->iob = ether->port;
31
 
32
	if (ether->irq==0)
33
		ether->irq=WDfltIRQ;
34
 
35
	if (ioalloc(ether->port,WIOLen,0,"wavelan")<0){
36
	//	print("#l%d: port 0x%lx in use\n",
37
	//			ether->ctlrno, ether->port);
38
		goto abort1;
39
	}
40
 
41
	/*
42
	 * If id= is specified, card must match.  Otherwise try generic.
43
	 */
44
	ctlr->slot = -1;
45
	for(i=0; i<ether->nopt; i++){
46
		if(cistrncmp(ether->opt[i], "id=", 3) == 0){
47
			if((ctlr->slot = pcmspecial(&ether->opt[i][3], ether)) < 0)
48
				goto abort;
49
			break;
50
		}
51
	}
52
	if(ctlr->slot == -1){
53
		for (i=0; wavenames[i]; i++)
54
			if((ctlr->slot = pcmspecial(wavenames[i], ether))>=0)
55
				break;
56
		if(!wavenames[i]){
57
			DEBUG("no wavelan found\n");
58
			goto abort;
59
		}
60
	}
61
 
62
	// DEBUG("#l%d: port=0x%lx irq=%ld\n",
63
	//		ether->ctlrno, ether->port, ether->irq);
64
 
65
	if(wavelanreset(ether, ctlr) < 0){
66
	abort:
67
		iofree(ether->port);
68
	abort1:
69
		iunlock(ctlr);
70
		free(ctlr);
71
		ether->ctlr = nil;
72
		return -1;
73
	}
74
 
75
	for(i = 0; i < ether->nopt; i++){
76
		if(p = strchr(ether->opt[i], '='))
77
			*p = ' ';
78
		w_option(ctlr, ether->opt[i], strlen(ether->opt[i]));
79
	}
80
 
81
	iunlock(ctlr);
82
	return 0;
83
}
84
 
85
static struct {
86
	int vid;
87
	int did;
88
} wavelanpci[] = {
89
	0x1260, 0x3873,	/* Intersil Prism2.5 */
90
	0x1737,	0x0019,	/* Linksys WPC-11 untested */
91
};
92
 
93
static Ctlr *ctlrhead, *ctlrtail;
94
 
95
static void
96
wavelanpciscan(void)
97
{
98
	int i;
99
	void *mem;
100
	Pcidev *p;
101
	Ctlr *ctlr;
102
 
103
	p = nil;
104
	while(p = pcimatch(p, 0, 0)){
105
		for(i=0; i<nelem(wavelanpci); i++)
106
			if(p->vid == wavelanpci[i].vid && p->did == wavelanpci[i].did)
107
				break;
108
		if(i==nelem(wavelanpci))
109
			continue;
110
 
111
		/*
112
		 * On the Prism, bar[0] is the memory-mapped register address (4KB),
113
		 */
114
		if(p->mem[0].size != 4096){
115
			print("wavelanpci: %.4ux %.4ux: unlikely mmio size\n", p->vid, p->did);
116
			continue;
117
		}
118
 
119
		ctlr = malloc(sizeof(Ctlr));
120
		if(ctlr == nil)
121
			error(Enomem);
122
		ctlr->pcidev = p;
123
		mem = vmap(p->mem[0].bar&~0xF, p->mem[0].size);
124
		if(mem == nil){
125
			print("wavelanpci: %.4ux %.4ux: vmap 0x%.8lux %d failed\n", p->vid, p->did, p->mem[0].bar&~0xF, p->mem[0].size);
126
			free(ctlr);
127
			continue;
128
		}
129
		ctlr->mmb = mem;
130
		if(ctlrhead != nil)
131
			ctlrtail->next = ctlr;
132
		else
133
			ctlrhead = ctlr;
134
		ctlrtail = ctlr;
135
		pcisetbme(p);
136
	}
137
}
138
 
139
static int
140
wavelanpcireset(Ether *ether)
141
{
142
	int i;
143
	char *p;
144
	Ctlr *ctlr;
145
 
146
	if(ctlrhead == nil)
147
		wavelanpciscan();
148
 
149
	/*
150
	 * Allow plan9.ini to set vid, did?
151
	 */
152
	for(ctlr=ctlrhead; ctlr!=nil; ctlr=ctlr->next)
153
		if(ctlr->active == 0)
154
			break;
155
	if(ctlr == nil)
156
		return -1;
157
 
158
	ctlr->active = 1;
159
	ilock(ctlr);
160
	ether->irq = ctlr->pcidev->intl;
161
	ether->tbdf = ctlr->pcidev->tbdf;
162
 
163
	/*
164
	 * Really hard reset.
165
	 */
166
	csr_outs(ctlr, WR_PciCor, 0x0080);
167
	delay(250);
168
	csr_outs(ctlr, WR_PciCor, 0x0000);
169
	delay(500);
170
	for(i=0; i<2*10; i++){
171
		if(!(csr_ins(ctlr, WR_Cmd)&WCmdBusy))
172
			break;
173
		delay(100);
174
	}
175
	if(i >= 2*10)
176
		print("wavelan pci %.4ux %.4ux: reset timeout %.4ux\n",
177
			ctlr->pcidev->vid, ctlr->pcidev->did, csr_ins(ctlr, WR_Cmd));
178
 
179
	if(wavelanreset(ether, ctlr) < 0){
180
		iunlock(ctlr);
181
		ether->ctlr = nil;
182
		return -1;
183
	}
184
 
185
	for(i = 0; i < ether->nopt; i++){
186
		if(p = strchr(ether->opt[i], '='))
187
			*p = ' ';
188
		w_option(ctlr, ether->opt[i], strlen(ether->opt[i]));
189
	}
190
	iunlock(ctlr);
191
	return 0;
192
}
193
 
194
void
195
etherwavelanlink(void)
196
{
197
	addethercard("wavelan", wavelanpcmciareset);
198
	addethercard("wavelanpci", wavelanpcireset);
199
}