|
@@ -1,4 +1,3 @@
|
1
|
|
-#ifdef CONFIG_ISA
|
2
|
1
|
/**************************************************************************
|
3
|
2
|
*
|
4
|
3
|
* isapnp.c -- Etherboot isapnp support for the 3Com 3c515
|
|
@@ -24,160 +23,265 @@
|
24
|
23
|
*
|
25
|
24
|
* REVISION HISTORY:
|
26
|
25
|
* ================
|
27
|
|
-* Version 0.1 April 26, 2002 TJL
|
28
|
|
-* Version 0.2 01/08/2003 TJL Moved outside the 3c515.c driver file
|
|
26
|
+* Version 0.1 April 26, 2002 TJL
|
|
27
|
+* Version 0.2 01/08/2003 TJL Moved outside the 3c515.c driver file
|
29
|
28
|
* Version 0.3 Sept 23, 2003 timlegge Change delay to currticks
|
30
|
29
|
*
|
31
|
30
|
*
|
32
|
|
-* Indent Options: indent -kr -i8
|
|
31
|
+* Generalised into an ISAPnP bus that can be used by more than just
|
|
32
|
+* the 3c515 by Michael Brown <mbrown@fensystems.co.uk>
|
|
33
|
+*
|
33
|
34
|
***************************************************************************/
|
34
|
35
|
|
35
|
|
-/* to get some global routines like printf */
|
36
|
36
|
#include "etherboot.h"
|
37
|
37
|
#include "timer.h"
|
38
|
38
|
#include "isapnp.h"
|
39
|
39
|
|
40
|
|
-static int pnp_card_csn = 0;
|
|
40
|
+/*
|
|
41
|
+ * We can have only one ISAPnP bus in a system. Once the read port is
|
|
42
|
+ * known and all cards have been allocated CSNs, there's nothing to be
|
|
43
|
+ * gained by re-scanning for cards.
|
|
44
|
+ *
|
|
45
|
+ * However, we shouldn't make scanning the ISAPnP bus an INIT_FN(),
|
|
46
|
+ * because even ISAPnP probing can still screw up other devices on the
|
|
47
|
+ * ISA bus. We therefore probe only when we are first asked to find
|
|
48
|
+ * an ISAPnP device.
|
|
49
|
+ *
|
|
50
|
+ */
|
|
51
|
+static uint16_t isapnp_read_port;
|
|
52
|
+static uint16_t isapnp_max_csn;
|
41
|
53
|
|
42
|
|
-void isapnp_wait(unsigned int nticks)
|
43
|
|
-{
|
44
|
|
- unsigned int to = currticks() + nticks;
|
45
|
|
- while (currticks() < to)
|
46
|
|
- /* Wait */ ;
|
|
54
|
+static const char initdata[] = INITDATA;
|
|
55
|
+
|
|
56
|
+/*
|
|
57
|
+ * ISAPnP utility functions
|
|
58
|
+ *
|
|
59
|
+ */
|
|
60
|
+
|
|
61
|
+static inline void isapnp_write_address ( uint8_t address ) {
|
|
62
|
+ outb ( address, ISAPNP_ADDRESS );
|
47
|
63
|
}
|
48
|
64
|
|
49
|
|
-/* The following code is the ISA PNP logic required to activate the 3c515 */
|
50
|
|
-/* PNP Defines */
|
51
|
|
-#define IDENT_LEN 9
|
52
|
|
-#define NUM_CARDS 128
|
53
|
|
-
|
54
|
|
-/* PNP declares */
|
55
|
|
-static unsigned char serial_identifier[NUM_CARDS + 1][IDENT_LEN];
|
56
|
|
-static unsigned char isapnp_checksum_value;
|
57
|
|
-static char initdata[INIT_LENGTH] = INITDATA;
|
58
|
|
-int read_port = 0;
|
59
|
|
-
|
60
|
|
-
|
61
|
|
-/* PNP Prototypes */
|
62
|
|
-static int Isolate(void);
|
63
|
|
-static int do_isapnp_isolate(void);
|
64
|
|
-static int isapnp_build_device_list(void);
|
65
|
|
-static int isapnp_isolate_rdp_select(void);
|
66
|
|
-static int isapnp_next_rdp(void);
|
67
|
|
-static void isapnp_peek(unsigned char *data, int bytes);
|
68
|
|
-static void send_key(void);
|
69
|
|
-static unsigned char isapnp_checksum(unsigned char *data);
|
70
|
|
-int Config(int csn);
|
71
|
|
-
|
72
|
|
-void config_pnp_device(void)
|
73
|
|
-{
|
74
|
|
- /* PNP Configuration */
|
75
|
|
- printf("Probing/Configuring ISAPNP devices\n");
|
76
|
|
- if (!read_port) {
|
77
|
|
- Isolate();
|
78
|
|
- if (pnp_card_csn)
|
79
|
|
- Config(pnp_card_csn);
|
|
65
|
+static inline void isapnp_write_data ( uint8_t data ) {
|
|
66
|
+ outb ( data, ISAPNP_WRITE_DATA );
|
|
67
|
+}
|
|
68
|
+
|
|
69
|
+static inline void isapnp_write_byte ( uint8_t address, uint8_t value ) {
|
|
70
|
+ isapnp_write_address ( address );
|
|
71
|
+ isapnp_write_data ( value );
|
|
72
|
+}
|
|
73
|
+
|
|
74
|
+static inline uint8_t isapnp_read_data ( void ) {
|
|
75
|
+ return inb ( isapnp_read_port );
|
|
76
|
+}
|
|
77
|
+
|
|
78
|
+static inline void isapnp_set_read_port ( void ) {
|
|
79
|
+ isapnp_write_byte ( ISAPNP_READPORT, isapnp_read_port >> 2 );
|
|
80
|
+}
|
|
81
|
+
|
|
82
|
+static inline void isapnp_serialisolation ( void ) {
|
|
83
|
+ isapnp_write_address ( ISAPNP_SERIALISOLATION );
|
|
84
|
+}
|
|
85
|
+
|
|
86
|
+static inline void isapnp_wait_for_key ( void ) {
|
|
87
|
+ isapnp_write_byte ( ISAPNP_CONFIGCONTROL, ISAPNP_CONFIG_WAIT_FOR_KEY );
|
|
88
|
+}
|
|
89
|
+
|
|
90
|
+static inline void isapnp_reset_csn ( void ) {
|
|
91
|
+ isapnp_write_byte ( ISAPNP_CONFIGCONTROL, ISAPNP_CONFIG_RESET_CSN );
|
|
92
|
+}
|
|
93
|
+
|
|
94
|
+static inline void isapnp_wake ( uint8_t csn ) {
|
|
95
|
+ isapnp_write_byte ( ISAPNP_WAKE, csn );
|
|
96
|
+}
|
|
97
|
+
|
|
98
|
+static inline void isapnp_write_csn ( uint8_t csn ) {
|
|
99
|
+ isapnp_write_byte ( ISAPNP_CARDSELECTNUMBER, csn );
|
|
100
|
+}
|
|
101
|
+
|
|
102
|
+/*
|
|
103
|
+ * The linear feedback shift register as described in Appendix B of
|
|
104
|
+ * the PnP ISA spec. The hardware implementation uses eight D-type
|
|
105
|
+ * latches and two XOR gates. I think this is probably the smallest
|
|
106
|
+ * possible implementation in software. :)
|
|
107
|
+ *
|
|
108
|
+ */
|
|
109
|
+static inline uint8_t isapnp_lfsr_next ( uint8_t lfsr, int input_bit ) {
|
|
110
|
+ register uint8_t lfsr_next;
|
|
111
|
+
|
|
112
|
+ lfsr_next = lfsr >> 1;
|
|
113
|
+ lfsr_next |= ( ( ( lfsr ^ lfsr_next ) ^ input_bit ) ) << 7;
|
|
114
|
+ return lfsr_next;
|
|
115
|
+}
|
|
116
|
+
|
|
117
|
+/*
|
|
118
|
+ * Send the ISAPnP initiation key
|
|
119
|
+ *
|
|
120
|
+ */
|
|
121
|
+static void isapnp_send_key ( void ) {
|
|
122
|
+ unsigned int i;
|
|
123
|
+ uint8_t lfsr;
|
|
124
|
+
|
|
125
|
+ udelay ( 1000 );
|
|
126
|
+ isapnp_write_address ( 0x00 );
|
|
127
|
+ isapnp_write_address ( 0x00 );
|
|
128
|
+
|
|
129
|
+ lfsr = ISAPNP_LFSR_SEED;
|
|
130
|
+ for ( i = 0 ; i < 32 ; i-- ) {
|
|
131
|
+ isapnp_write_address ( lfsr );
|
|
132
|
+ lfsr = isapnp_lfsr_next ( lfsr, 0 );
|
80
|
133
|
}
|
81
|
134
|
}
|
82
|
135
|
|
83
|
|
-/* Isolate all the PNP Boards on the ISA BUS */
|
84
|
|
-static int Isolate(void)
|
85
|
|
-{
|
86
|
|
- int cards = 0;
|
87
|
|
- if (read_port < 0x203 || read_port > 0x3ff) {
|
88
|
|
- cards = do_isapnp_isolate();
|
89
|
|
- if (cards < 0 || (read_port < 0x203 || read_port > 0x3ff)) {
|
90
|
|
- printf("No Plug & Play device found\n");
|
91
|
|
- return 0;
|
|
136
|
+/*
|
|
137
|
+ * Compute ISAPnP identifier checksum
|
|
138
|
+ *
|
|
139
|
+ */
|
|
140
|
+static uint8_t isapnp_checksum ( union isapnp_identifier *identifier ) {
|
|
141
|
+ int i, j;
|
|
142
|
+ uint8_t lfsr;
|
|
143
|
+ uint8_t byte;
|
|
144
|
+
|
|
145
|
+ lfsr = ISAPNP_LFSR_SEED;
|
|
146
|
+ for ( i = 0 ; i < 8 ; i++ ) {
|
|
147
|
+ byte = identifier->bytes[i];
|
|
148
|
+ for ( j = 0 ; j < 8 ; j++ ) {
|
|
149
|
+ lfsr = isapnp_lfsr_next ( lfsr, byte );
|
|
150
|
+ byte >>= 1;
|
92
|
151
|
}
|
93
|
152
|
}
|
94
|
|
- isapnp_build_device_list();
|
95
|
|
-#ifdef EDEBUG
|
96
|
|
- printf("%d Plug & Play device found\n", cards);
|
97
|
|
-#endif
|
98
|
|
- return 0;
|
|
153
|
+ return lfsr;
|
99
|
154
|
}
|
100
|
155
|
|
101
|
|
-static int do_isapnp_isolate(void)
|
102
|
|
-{
|
103
|
|
- unsigned char checksum = 0x6a;
|
104
|
|
- unsigned char chksum = 0x00;
|
105
|
|
- unsigned char bit = 0x00;
|
106
|
|
- unsigned char c1, c2;
|
107
|
|
- int csn = 0;
|
108
|
|
- int i;
|
109
|
|
- int iteration = 1;
|
110
|
|
-
|
111
|
|
- read_port = 0x213;
|
112
|
|
- if (isapnp_isolate_rdp_select() < 0)
|
113
|
|
- return -1;
|
114
|
|
-
|
115
|
|
- while (1) {
|
116
|
|
- for (i = 1; i <= 64; i++) {
|
117
|
|
- c1 = READ_DATA;
|
118
|
|
- isapnp_wait(1);
|
119
|
|
- c2 = READ_DATA;
|
120
|
|
- isapnp_wait(1);
|
121
|
|
- if (c1 == 0x55) {
|
122
|
|
- if (c2 == 0xAA) {
|
123
|
|
- bit = 0x01;
|
|
156
|
+/*
|
|
157
|
+ * Try isolating ISAPnP cards at the current read port. Return the
|
|
158
|
+ * number of ISAPnP cards found.
|
|
159
|
+ *
|
|
160
|
+ * The state diagram on page 18 (PDF page 24) of the PnP ISA spec
|
|
161
|
+ * gives the best overview of what happens here.
|
|
162
|
+ *
|
|
163
|
+ */
|
|
164
|
+static int isapnp_try_isolate ( void ) {
|
|
165
|
+ union isapnp_identifier identifier;
|
|
166
|
+ int i, j, seen55aa;
|
|
167
|
+ uint16_t data;
|
|
168
|
+ uint8_t byte;
|
|
169
|
+
|
|
170
|
+ DBG ( "ISAPnP attempting isolation at read port %hx\n",
|
|
171
|
+ isapnp_read_port );
|
|
172
|
+
|
|
173
|
+ /* Place all cards into the Sleep state, whatever state
|
|
174
|
+ * they're currently in.
|
|
175
|
+ */
|
|
176
|
+ isapnp_wait_for_key ();
|
|
177
|
+ isapnp_send_key ();
|
|
178
|
+
|
|
179
|
+ /* Reset all assigned CSNs */
|
|
180
|
+ isapnp_reset_csn ();
|
|
181
|
+ isapnp_max_csn = 0;
|
|
182
|
+ udelay ( 2000 );
|
|
183
|
+
|
|
184
|
+ /* Place all cards into the Isolation state */
|
|
185
|
+ isapnp_wait_for_key ();
|
|
186
|
+ isapnp_send_key ();
|
|
187
|
+ isapnp_wake ( 0x00 );
|
|
188
|
+
|
|
189
|
+ /* Set the read port */
|
|
190
|
+ isapnp_set_read_port ();
|
|
191
|
+ udelay ( 1000 );
|
|
192
|
+
|
|
193
|
+ while ( 1 ) {
|
|
194
|
+
|
|
195
|
+ /* All cards that do not have assigned CSNs are
|
|
196
|
+ * currently in the Isolation state, each time we go
|
|
197
|
+ * through this loop.
|
|
198
|
+ */
|
|
199
|
+
|
|
200
|
+ /* Initiate serial isolation */
|
|
201
|
+ isapnp_serialisolation ();
|
|
202
|
+ udelay ( 1000 );
|
|
203
|
+
|
|
204
|
+ /* Read identifier serially via the ISAPnP read port. */
|
|
205
|
+ memset ( &identifier, 0, sizeof ( identifier ) );
|
|
206
|
+ seen55aa = 0;
|
|
207
|
+ for ( i = 0 ; i < 9 ; i++ ) {
|
|
208
|
+ byte = 0;
|
|
209
|
+ for ( j = 0 ; j < 8 ; j++ ) {
|
|
210
|
+ data = isapnp_read_data ();
|
|
211
|
+ udelay ( 1000 );
|
|
212
|
+ data = ( data << 8 ) | isapnp_read_data ();
|
|
213
|
+ udelay ( 1000 );
|
|
214
|
+ if ( data == 0x55aa ) {
|
|
215
|
+ byte |= 1;
|
124
|
216
|
}
|
|
217
|
+ byte <<= 1;
|
125
|
218
|
}
|
126
|
|
- checksum =
|
127
|
|
- ((((checksum ^ (checksum >> 1)) & 0x01) ^ bit)
|
128
|
|
- << 7) | (checksum >> 1);
|
129
|
|
- bit = 0x00;
|
130
|
|
- }
|
131
|
|
-#ifdef EDEBUG
|
132
|
|
- printf("Calc checksum %d", checksum);
|
133
|
|
-#endif
|
134
|
|
- for (i = 65; i <= 72; i++) {
|
135
|
|
- c1 = READ_DATA;
|
136
|
|
- udelay(250);
|
137
|
|
- c2 = READ_DATA;
|
138
|
|
- udelay(250);
|
139
|
|
- if (c1 == 0x55) {
|
140
|
|
- if (c2 == 0xAA)
|
141
|
|
- chksum |= (1 << (i - 65));
|
|
219
|
+ identifier.bytes[i] = byte;
|
|
220
|
+ if ( byte ) {
|
|
221
|
+ seen55aa = 1;
|
142
|
222
|
}
|
143
|
223
|
}
|
144
|
|
-#ifdef EDEBUG
|
145
|
|
- printf("Actual checksum %d", chksum);
|
146
|
|
-#endif
|
147
|
|
- if (checksum != 0x00 && checksum == chksum) {
|
148
|
|
- csn++;
|
149
|
|
- serial_identifier[csn][iteration] >>= 1;
|
150
|
|
- serial_identifier[csn][iteration] |= bit;
|
151
|
|
- CARDSELECTNUMBER;
|
152
|
|
-#ifdef EDEBUG
|
153
|
|
- printf("Writing csn: %d", csn);
|
154
|
|
-#endif
|
155
|
|
- WRITE_DATA(csn);
|
156
|
|
- udelay(250);
|
157
|
|
- iteration++;
|
158
|
|
- /* Force all cards without a CSN into Isolation state */
|
159
|
|
- Wake(0);
|
160
|
|
- SetRdPort(read_port);
|
161
|
|
- udelay(1000);
|
162
|
|
- SERIALISOLATION;
|
163
|
|
- udelay(1000);
|
164
|
|
- goto __next;
|
165
|
|
- }
|
166
|
|
- if (iteration == 1) {
|
167
|
|
- read_port += READ_ADDR_STEP;
|
168
|
|
- if (isapnp_isolate_rdp_select() < 0)
|
169
|
|
- return -1;
|
170
|
|
- } else if (iteration > 1) {
|
|
224
|
+
|
|
225
|
+ /* If we didn't see a valid ISAPnP device, stop here */
|
|
226
|
+ if ( ( ! seen55aa ) ||
|
|
227
|
+ ( identifier.checksum != isapnp_checksum (&identifier) ) )
|
171
|
228
|
break;
|
172
|
|
- }
|
173
|
|
- __next:
|
174
|
|
- checksum = 0x6a;
|
175
|
|
- chksum = 0x00;
|
176
|
|
- bit = 0x00;
|
|
229
|
+
|
|
230
|
+ /* Give the device a CSN */
|
|
231
|
+ isapnp_max_csn++;
|
|
232
|
+ DBG ( "ISAPnP isolation found device "
|
|
233
|
+ "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx "
|
|
234
|
+ "(checksum %hhx), assigning CSN %hhx\n",
|
|
235
|
+ identifier.bytes[0], identifier.bytes[1],
|
|
236
|
+ identifier.bytes[2], identifier.bytes[3],
|
|
237
|
+ identifier.bytes[4], identifier.bytes[5],
|
|
238
|
+ identifier.bytes[6], identifier.bytes[7],
|
|
239
|
+ identifier.checksum, isapnp_max_csn );
|
|
240
|
+
|
|
241
|
+ isapnp_write_csn ( isapnp_max_csn );
|
|
242
|
+ udelay ( 1000 );
|
|
243
|
+
|
|
244
|
+ /* Send this card back to Sleep and force all cards
|
|
245
|
+ * without a CSN into Isolation state
|
|
246
|
+ */
|
|
247
|
+ isapnp_wake ( 0x00 );
|
|
248
|
+ udelay ( 1000 );
|
177
|
249
|
}
|
178
|
|
- return csn;
|
|
250
|
+
|
|
251
|
+ /* Place all cards in Wait for Key state */
|
|
252
|
+ isapnp_wait_for_key ();
|
|
253
|
+
|
|
254
|
+ /* Return number of cards found */
|
|
255
|
+ DBG ( "ISAPnP found %d devices at read port %hx\n", isapnp_read_port );
|
|
256
|
+ return isapnp_max_csn;
|
179
|
257
|
}
|
180
|
258
|
|
|
259
|
+/*
|
|
260
|
+ * Isolate all ISAPnP cards, locating a valid read port in the process.
|
|
261
|
+ *
|
|
262
|
+ */
|
|
263
|
+static void isapnp_isolate ( void ) {
|
|
264
|
+ for ( isapnp_read_port = ISAPNP_READ_PORT_MIN ;
|
|
265
|
+ isapnp_read_port <= ISAPNP_READ_PORT_MAX ;
|
|
266
|
+ isapnp_read_port += ISAPNP_READ_PORT_STEP ) {
|
|
267
|
+ /* Avoid problematic locations such as the NE2000
|
|
268
|
+ * probe space
|
|
269
|
+ */
|
|
270
|
+ if ( ( isapnp_read_port >= 0x280 ) &&
|
|
271
|
+ ( isapnp_read_port <= 0x380 ) )
|
|
272
|
+ continue;
|
|
273
|
+
|
|
274
|
+ /* If we detect any ISAPnP cards at this location, stop */
|
|
275
|
+ if ( isapnp_try_isolate () )
|
|
276
|
+ return;
|
|
277
|
+ }
|
|
278
|
+}
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
|
181
|
285
|
/*
|
182
|
286
|
* Build device list for all present ISA PnP devices.
|
183
|
287
|
*/
|
|
@@ -277,20 +381,6 @@ int Config(int csn)
|
277
|
381
|
return 1;
|
278
|
382
|
}
|
279
|
383
|
|
280
|
|
-static void send_key(void)
|
281
|
|
-{
|
282
|
|
- int i;
|
283
|
|
- /* Ask for access to the Wait for Key command - ConfigControl register */
|
284
|
|
- CONFIGCONTROL;
|
285
|
|
- /* Write the Wait for Key Command to the ConfigControl Register */
|
286
|
|
- WRITE_DATA(CONFIG_WAIT_FOR_KEY);
|
287
|
|
- /* As per doc. Two Write cycles of 0x00 required befor the Initialization key is sent */
|
288
|
|
- ADDRESS(0);
|
289
|
|
- ADDRESS(0);
|
290
|
|
- /* 32 writes of the initiation key to the card */
|
291
|
|
- for (i = 0; i < INIT_LENGTH; i++)
|
292
|
|
- ADDRESS(initdata[i]);
|
293
|
|
-}
|
294
|
384
|
|
295
|
385
|
static void isapnp_peek(unsigned char *data, int bytes)
|
296
|
386
|
{
|
|
@@ -316,67 +406,111 @@ static void isapnp_peek(unsigned char *data, int bytes)
|
316
|
406
|
}
|
317
|
407
|
}
|
318
|
408
|
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
|
319
|
412
|
/*
|
320
|
|
- * Compute ISA PnP checksum for first eight bytes.
|
|
413
|
+ * Ensure that there is sufficient space in the shared dev_bus
|
|
414
|
+ * structure for a struct isapnp_device.
|
|
415
|
+ *
|
321
|
416
|
*/
|
322
|
|
-static unsigned char isapnp_checksum(unsigned char *data)
|
323
|
|
-{
|
324
|
|
- int i, j;
|
325
|
|
- unsigned char checksum = 0x6a, bit, b;
|
326
|
|
-
|
327
|
|
- for (i = 0; i < 8; i++) {
|
328
|
|
- b = data[i];
|
329
|
|
- for (j = 0; j < 8; j++) {
|
330
|
|
- bit = 0;
|
331
|
|
- if (b & (1 << j))
|
332
|
|
- bit = 1;
|
333
|
|
- checksum =
|
334
|
|
- ((((checksum ^ (checksum >> 1)) & 0x01) ^ bit)
|
335
|
|
- << 7) | (checksum >> 1);
|
336
|
|
- }
|
|
417
|
+DEV_BUS( struct isapnp_device, isapnp_dev );
|
|
418
|
+static char isapnp_magic[0]; /* guaranteed unique symbol */
|
|
419
|
+
|
|
420
|
+/*
|
|
421
|
+ * Fill in parameters for an ISAPnP device based on CSN
|
|
422
|
+ *
|
|
423
|
+ * Return 1 if device present, 0 otherwise
|
|
424
|
+ *
|
|
425
|
+ */
|
|
426
|
+static int fill_isapnp_device ( struct isapnp_device *isapnp ) {
|
|
427
|
+
|
|
428
|
+ /*
|
|
429
|
+ * Ensure that all ISAPnP cards have CSNs allocated to them,
|
|
430
|
+ * if we haven't already done so.
|
|
431
|
+ *
|
|
432
|
+ */
|
|
433
|
+ if ( ! isapnp_read_port ) {
|
|
434
|
+ isapnp_isolate();
|
337
|
435
|
}
|
338
|
|
- return checksum;
|
|
436
|
+
|
|
437
|
+ /* wake csn, read config, send card to sleep */
|
|
438
|
+
|
|
439
|
+ DBG ( "ISAPnP found CSN %hhx ID %hx:%hx (\"%s\")\n",
|
|
440
|
+ isapnp->csn, isapnp->vendor_id, isapnp->prod_id,
|
|
441
|
+ isa_id_string ( isapnp->vendor_id, isapnp->prod_id ) );
|
|
442
|
+
|
|
443
|
+ return 0;
|
339
|
444
|
}
|
340
|
|
-static int isapnp_next_rdp(void)
|
341
|
|
-{
|
342
|
|
- int rdp = read_port;
|
343
|
|
- while (rdp <= 0x3ff) {
|
344
|
|
- /*
|
345
|
|
- * We cannot use NE2000 probe spaces for ISAPnP or we
|
346
|
|
- * will lock up machines.
|
347
|
|
- */
|
348
|
|
- if ((rdp < 0x280 || rdp > 0x380)) {
|
349
|
|
- read_port = rdp;
|
350
|
|
- return 0;
|
351
|
|
- }
|
352
|
|
- rdp += READ_ADDR_STEP;
|
|
445
|
+
|
|
446
|
+/*
|
|
447
|
+ * Find an ISAPnP device matching the specified driver
|
|
448
|
+ *
|
|
449
|
+ */
|
|
450
|
+int find_isapnp_device ( struct isapnp_device *isapnp,
|
|
451
|
+ struct isapnp_driver *driver ) {
|
|
452
|
+ unsigned int i;
|
|
453
|
+
|
|
454
|
+ /* Initialise struct isapnp if it's the first time it's been used. */
|
|
455
|
+ if ( isapnp->magic != isapnp_magic ) {
|
|
456
|
+ memset ( isapnp, 0, sizeof ( *isapnp ) );
|
|
457
|
+ isapnp->magic = isapnp_magic;
|
|
458
|
+ isapnp->csn = 1;
|
353
|
459
|
}
|
354
|
|
- return -1;
|
355
|
|
-}
|
356
|
460
|
|
357
|
|
-static int isapnp_isolate_rdp_select(void)
|
358
|
|
-{
|
359
|
|
- send_key();
|
360
|
|
- /* Control: reset CSN and conditionally everything else too */
|
361
|
|
- CONFIGCONTROL;
|
362
|
|
- WRITE_DATA((CONFIG_RESET_CSN | CONFIG_WAIT_FOR_KEY));
|
363
|
|
- mdelay(2);
|
364
|
|
-
|
365
|
|
- send_key();
|
366
|
|
- Wake(0);
|
367
|
|
-
|
368
|
|
- if (isapnp_next_rdp() < 0) {
|
369
|
|
- /* Ask for access to the Wait for Key command - ConfigControl register */
|
370
|
|
- CONFIGCONTROL;
|
371
|
|
- /* Write the Wait for Key Command to the ConfigControl Register */
|
372
|
|
- WRITE_DATA(CONFIG_WAIT_FOR_KEY);
|
373
|
|
- return -1;
|
|
461
|
+ /* Iterate through all possible ISAPNP CSNs, starting where we
|
|
462
|
+ * left off.
|
|
463
|
+ */
|
|
464
|
+ for ( ; isapnp->csn <= isapnp_max_csn ; isapnp->csn++ ) {
|
|
465
|
+ /* If we've already used this device, skip it */
|
|
466
|
+ if ( isapnp->already_tried ) {
|
|
467
|
+ isapnp->already_tried = 0;
|
|
468
|
+ continue;
|
|
469
|
+ }
|
|
470
|
+
|
|
471
|
+ /* Fill in device parameters */
|
|
472
|
+ if ( ! fill_isapnp_device ( isapnp ) ) {
|
|
473
|
+ continue;
|
|
474
|
+ }
|
|
475
|
+
|
|
476
|
+ /* Compare against driver's ID list */
|
|
477
|
+ for ( i = 0 ; i < driver->id_count ; i++ ) {
|
|
478
|
+ struct isapnp_id *id = &driver->ids[i];
|
|
479
|
+
|
|
480
|
+ if ( ( isapnp->vendor_id == id->vendor_id ) &&
|
|
481
|
+ ( ISA_PROD_ID ( isapnp->prod_id ) ==
|
|
482
|
+ ISA_PROD_ID ( id->prod_id ) ) ) {
|
|
483
|
+ DBG ( "Device %s (driver %s) matches ID %s\n",
|
|
484
|
+ id->name, driver->name,
|
|
485
|
+ isa_id_string ( isapnp->vendor_id,
|
|
486
|
+ isapnp->prod_id ) );
|
|
487
|
+ isapnp->name = id->name;
|
|
488
|
+ isapnp->already_tried = 1;
|
|
489
|
+ return 1;
|
|
490
|
+ }
|
|
491
|
+ }
|
374
|
492
|
}
|
375
|
493
|
|
376
|
|
- SetRdPort(read_port);
|
377
|
|
- udelay(1000);
|
378
|
|
- SERIALISOLATION;
|
379
|
|
- udelay(1000);
|
|
494
|
+ /* No device found */
|
|
495
|
+ isapnp->csn = 1;
|
380
|
496
|
return 0;
|
381
|
497
|
}
|
382
|
|
-#endif /* CONFIG_ISA */
|
|
498
|
+
|
|
499
|
+/*
|
|
500
|
+ * Find the next ISAPNP device that can be used to boot using the
|
|
501
|
+ * specified driver.
|
|
502
|
+ *
|
|
503
|
+ */
|
|
504
|
+int find_isapnp_boot_device ( struct dev *dev, struct isapnp_driver *driver ) {
|
|
505
|
+ struct isapnp_device *isapnp = ( struct isapnp_device * ) dev->bus;
|
|
506
|
+
|
|
507
|
+ if ( ! find_isapnp_device ( isapnp, driver ) )
|
|
508
|
+ return 0;
|
|
509
|
+
|
|
510
|
+ dev->name = isapnp->name;
|
|
511
|
+ dev->devid.bus_type = ISA_BUS_TYPE;
|
|
512
|
+ dev->devid.vendor_id = isapnp->vendor_id;
|
|
513
|
+ dev->devid.device_id = isapnp->prod_id;
|
|
514
|
+
|
|
515
|
+ return 1;
|
|
516
|
+}
|