Ver código fonte

Cleaned up isolation protocol.

tags/v0.9.3
Michael Brown 19 anos atrás
pai
commit
1980018b8b
2 arquivos alterados com 441 adições e 244 exclusões
  1. 330
    196
      src/drivers/bus/isapnp.c
  2. 111
    48
      src/include/isapnp.h

+ 330
- 196
src/drivers/bus/isapnp.c Ver arquivo

@@ -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
+}

+ 111
- 48
src/include/isapnp.h Ver arquivo

@@ -18,69 +18,65 @@
18 18
 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 19
 *
20 20
 *    Portions of this code:
21
-*				Copyright (C) 2001  P.J.H.Fox (fox@roestock.demon.co.uk)
21
+*		Copyright (C) 2001  P.J.H.Fox (fox@roestock.demon.co.uk)
22 22
 *
23 23
 *
24 24
 *
25 25
 *    REVISION HISTORY:
26 26
 *    ================
27 27
 *        Version 0.1 April 26, 2002 	TJL
28
-*		 Version 0.2 01/08/2003			TJL Renamed from 3c515_isapnp.h
28
+*	 Version 0.2 01/08/2003			TJL Renamed from 3c515_isapnp.h
29
+*
30
+*
31
+*    Generalised into an ISAPnP bus that can be used by more than just
32
+*    the 3c515 by Michael Brown <mbrown@fensystems.co.uk>
29 33
 *
30 34
 ***************************************************************************/
31 35
 
32
-/*extern int read_port;*/
33
-/*#define DEBUG*/
34
-#define ADDRESS_ADDR 0x0279
35
-#define WRITEDATA_ADDR 0x0a79
36
-/* MIN and MAX READ_ADDR must have the bottom two bits set */
37
-#define MIN_READ_ADDR 0x0203
38
-#define START_READ_ADDR 0x203
39
-#define MAX_READ_ADDR 0x03ff
40
-/* READ_ADDR_STEP must be a multiple of 4 */
41
-#ifndef READ_ADDR_STEP
42
-#define READ_ADDR_STEP 8
43
-#endif
44
-
45
-#ifdef EDEBUG
46
-static int x;
47
-#define ADDRESS(x) (outb(x, ADDRESS_ADDR), printf("\nAddress: %hX", x))
48
-#define WRITE_DATA(x) (outb(x, WRITEDATA_ADDR), printf(" WR(%hX)", x & 0xff))
49
-#define READ_DATA (x = inb(read_port), printf(" RD(%hX)", x & 0xff), x)
50
-#define READ_IOPORT(p) (x = inb(p), printf(" [%hX](%hX)", p, x & 0xff), x)
51
-#else				/* !DEBUG */
52
-#define ADDRESS(x) outb(x, ADDRESS_ADDR)
53
-#define WRITE_DATA(x) outb(x, WRITEDATA_ADDR)
54
-#define READ_DATA inb(read_port)
55
-#define READ_IOPORT(p) inb(p)
56
-#endif				/* !DEBUG */
36
+#ifndef ISAPNP_H
37
+#define ISAPNP_H
57 38
 
39
+#include "isa_ids.h"
40
+#include "dev.h"
58 41
 
42
+/*
43
+ * ISAPnP constants
44
+ *
45
+ */
59 46
 
60
-#define INIT_LENGTH 32
61
-
62
-#define INITDATA { 0x6a, 0xb5, 0xda, 0xed, 0xf6, 0xfb, 0x7d, 0xbe,\
63
-                   0xdf, 0x6f, 0x37, 0x1b, 0x0d, 0x86, 0xc3, 0x61,\
64
-                   0xb0, 0x58, 0x2c, 0x16, 0x8b, 0x45, 0xa2, 0xd1,\
65
-                   0xe8, 0x74, 0x3a, 0x9d, 0xce, 0xe7, 0x73, 0x39 }
47
+/* Port addresses */
48
+#define ISAPNP_ADDRESS		0x279
49
+#define ISAPNP_WRITE_DATA	0xa79
50
+#define ISAPNP_READ_PORT_MIN	0x213	/* ISAPnP spec says 0x203, but
51
+					 * Linux ISAPnP starts at
52
+					 * 0x213 with no explanatory
53
+					 * comment.  0x203 probably
54
+					 * clashes with something. */
55
+#define ISAPNP_READ_PORT_MAX	0x3ff
56
+#define ISAPNP_READ_PORT_STEP	0x08	/* Can be any multiple of 4 */
66 57
 
67 58
 /* Registers */
68
-#define SetRdPort(x)		(ADDRESS(0x00),WRITE_DATA((x)>>2),read_port=((x)|3))
69
-#define SERIALISOLATION 	ADDRESS(0x01)
70
-#define CONFIGCONTROL		ADDRESS(0x02)
71
-#define Wake(x)				(ADDRESS(0x03),WRITE_DATA(x))
72
-#define RESOURCEDATA		(ADDRESS(0x04),READ_DATA)
73
-#define STATUS          	(ADDRESS(0x05),READ_DATA)
74
-#define CARDSELECTNUMBER	ADDRESS(0x06)
75
-#define LOGICALDEVICENUMBER	ADDRESS(0x07)
76
-#define ACTIVATE			ADDRESS(0x30)
77
-#define IORANGECHECK		ADDRESS(0x31)
59
+#define ISAPNP_READPORT			0x00
60
+#define ISAPNP_SERIALISOLATION 		0x01
61
+#define ISAPNP_CONFIGCONTROL		0x02
62
+#define ISAPNP_WAKE			0x03
63
+#define ISAPNP_RESOURCEDATA		0x04
64
+#define ISAPNP_STATUS          		0x05
65
+#define ISAPNP_CARDSELECTNUMBER		0x06
66
+#define ISAPNP_LOGICALDEVICENUMBER	0x07
67
+#define ISAPNP_ACTIVATE			0x30
68
+#define ISAPNP_IORANGECHECK		0x31
69
+
70
+/* Bits in the CONFIGCONTROL register */
71
+#define ISAPNP_CONFIG_RESET		( 1 << 0 )
72
+#define ISAPNP_CONFIG_WAIT_FOR_KEY	( 1 << 1 )
73
+#define ISAPNP_CONFIG_RESET_CSN		( 1 << 2 )
74
+#define ISAPNP_CONFIG_RESET_DRV		( ISAPNP_CONFIG_RESET | 	\
75
+					  ISAPNP_CONFIG_WAIT_FOR_KEY |	\
76
+					  ISAPNP_CONFIG_RESET_CSN )
78 77
 
79
-/* Bits */
80
-#define CONFIG_RESET		0x01
81
-#define CONFIG_WAIT_FOR_KEY 0x02
82
-#define CONFIG_RESET_CSN	0x04
83
-#define CONFIG_RESET_DRV	0x07
78
+/* The LFSR used for the initiation key and for checksumming */
79
+#define ISAPNP_LFSR_SEED	0x6a
84 80
 
85 81
 /* Short  Tags */
86 82
 #define PnPVerNo_TAG		0x01
@@ -122,3 +118,70 @@ static int x;
122 118
 #define RsvdLongE_TAG		0xFE
123 119
 #define RsvdLongF_TAG		0xFF
124 120
 #define NewBoard_PSEUDOTAG	0x100
121
+
122
+/*
123
+ * An ISAPnP serial identifier
124
+ *
125
+ */
126
+union isapnp_identifier {
127
+	char bytes[9];
128
+	struct {
129
+		uint16_t vendor_id;
130
+		uint16_t product_id;
131
+		uint32_t serial;
132
+		uint8_t checksum;
133
+	} __attribute__ (( packed ));
134
+} __attribute__ (( packed ));
135
+
136
+/*
137
+ * A physical ISAPnP device
138
+ *
139
+ */
140
+struct isapnp_device {
141
+	char *magic; /* must be first */
142
+	const char *name;
143
+	unsigned char csn;
144
+	uint16_t vendor_id;
145
+	uint16_t prod_id;
146
+	int already_tried;
147
+};
148
+
149
+/*
150
+ * An individual ISAPnP device identified by ID
151
+ *
152
+ */
153
+struct isapnp_id {
154
+        const char *name;
155
+	uint16_t vendor_id, prod_id;
156
+};
157
+
158
+/*
159
+ * An ISAPnP driver, with a device ID (struct isapnp_id) table.
160
+ *
161
+ */
162
+struct isapnp_driver {
163
+	const char *name;
164
+	struct isapnp_id *ids;
165
+	unsigned int id_count;
166
+};
167
+
168
+/*
169
+ * Define an ISAPnP driver
170
+ *
171
+ */
172
+#define ISAPNP_DRIVER( driver_name, isapnp_ids ) {			\
173
+	.name = driver_name,						\
174
+	.ids = isapnp_ids,						\
175
+	.id_count = sizeof ( isapnp_ids ) / sizeof ( isapnp_ids[0] ),	\
176
+}
177
+
178
+/*
179
+ * Functions in isapnp.c
180
+ *
181
+ */
182
+extern int find_isapnp_device ( struct isapnp_device *isapnp,
183
+				struct isapnp_driver *driver );
184
+extern int find_isapnp_boot_device ( struct dev *dev,
185
+				     struct isapnp_driver *driver );
186
+
187
+#endif /* ISAPNP_H */

Carregando…
Cancelar
Salvar