Ver código fonte

Activation code now generalised as well.

tags/v0.9.3
Michael Brown 19 anos atrás
pai
commit
85dd4fd8d6
2 arquivos alterados com 149 adições e 151 exclusões
  1. 144
    150
      src/drivers/bus/isapnp.c
  2. 5
    1
      src/include/isapnp.h

+ 144
- 150
src/drivers/bus/isapnp.c Ver arquivo

@@ -35,8 +35,17 @@
35 35
 
36 36
 #include "etherboot.h"
37 37
 #include "timer.h"
38
+#include "io.h"
38 39
 #include "isapnp.h"
39 40
 
41
+/*
42
+ * Ensure that there is sufficient space in the shared dev_bus
43
+ * structure for a struct isapnp_device.
44
+ *
45
+ */
46
+DEV_BUS( struct isapnp_device, isapnp_dev );
47
+static char isapnp_magic[0]; /* guaranteed unique symbol */
48
+
40 49
 /*
41 50
  * We can have only one ISAPnP bus in a system.  Once the read port is
42 51
  * known and all cards have been allocated CSNs, there's nothing to be
@@ -51,8 +60,6 @@
51 60
 static uint16_t isapnp_read_port;
52 61
 static uint16_t isapnp_max_csn;
53 62
 
54
-static const char initdata[] = INITDATA;
55
-
56 63
 /*
57 64
  * ISAPnP utility functions
58 65
  *
@@ -66,13 +73,18 @@ static inline void isapnp_write_data ( uint8_t data ) {
66 73
 	outb ( data, ISAPNP_WRITE_DATA );
67 74
 }
68 75
 
76
+static inline uint8_t isapnp_read_data ( void ) {
77
+	return inb ( isapnp_read_port );
78
+}
79
+
69 80
 static inline void isapnp_write_byte ( uint8_t address, uint8_t value ) {
70 81
 	isapnp_write_address ( address );
71 82
 	isapnp_write_data ( value );
72 83
 }
73 84
 
74
-static inline uint8_t isapnp_read_data ( void ) {
75
-	return inb ( isapnp_read_port );
85
+static inline uint8_t isapnp_read_byte ( uint8_t address ) {
86
+	isapnp_write_address ( address );
87
+	return isapnp_read_data ();
76 88
 }
77 89
 
78 90
 static inline void isapnp_set_read_port ( void ) {
@@ -95,10 +107,32 @@ static inline void isapnp_wake ( uint8_t csn ) {
95 107
 	isapnp_write_byte ( ISAPNP_WAKE, csn );
96 108
 }
97 109
 
110
+static inline uint8_t isapnp_read_resourcedata ( void ) {
111
+	return isapnp_read_byte ( ISAPNP_RESOURCEDATA );
112
+}
113
+
114
+static inline uint8_t isapnp_read_status ( void ) {
115
+	return isapnp_read_byte ( ISAPNP_STATUS );
116
+}
117
+
98 118
 static inline void isapnp_write_csn ( uint8_t csn ) {
99 119
 	isapnp_write_byte ( ISAPNP_CARDSELECTNUMBER, csn );
100 120
 }
101 121
 
122
+static inline void isapnp_logicaldevice ( uint8_t logdev ) {
123
+	isapnp_write_byte ( ISAPNP_LOGICALDEVICENUMBER, logdev );
124
+}
125
+
126
+static inline void isapnp_activate ( uint8_t logdev ) {
127
+	isapnp_logicaldevice ( logdev );
128
+	isapnp_write_byte ( ISAPNP_ACTIVATE, 1 );
129
+}
130
+
131
+static inline void isapnp_deactivate ( uint8_t logdev ) {
132
+	isapnp_logicaldevice ( logdev );
133
+	isapnp_write_byte ( ISAPNP_ACTIVATE, 0 );
134
+}
135
+
102 136
 /*
103 137
  * The linear feedback shift register as described in Appendix B of
104 138
  * the PnP ISA spec.  The hardware implementation uses eight D-type
@@ -153,6 +187,42 @@ static uint8_t isapnp_checksum ( union isapnp_identifier *identifier ) {
153 187
 	return lfsr;
154 188
 }
155 189
 
190
+/*
191
+ * Read a byte of resource data from the current location
192
+ *
193
+ */
194
+static inline uint8_t isapnp_peek_byte ( void ) {
195
+	int i;
196
+
197
+	/* Wait for data to be ready */
198
+	for ( i = 0 ; i < 20 ; i ++ ) {
199
+		if ( isapnp_read_status() & 0x01 ) {
200
+			/* Byte ready - read it */
201
+			return isapnp_read_resourcedata();
202
+		}
203
+		udelay ( 100 );
204
+	}
205
+	/* Data never became ready - return 0xff */
206
+	return 0xff;
207
+}
208
+
209
+/*
210
+ * Read n bytes of resource data from the current location.  If buf is
211
+ * NULL, discard data.
212
+ *
213
+ */
214
+static void isapnp_peek ( uint8_t *buf, size_t bytes ) {
215
+	unsigned int i;
216
+	uint8_t byte;
217
+
218
+	for ( i = 0 ; i < bytes ; i++) {
219
+		byte = isapnp_peek_byte();
220
+		if ( buf ) {
221
+			buf[i] = byte;
222
+		}
223
+	}
224
+}
225
+
156 226
 /*
157 227
  * Try isolating ISAPnP cards at the current read port.  Return the
158 228
  * number of ISAPnP cards found.
@@ -277,146 +347,6 @@ static void isapnp_isolate ( void ) {
277 347
 	}
278 348
 }
279 349
 
280
-
281
-
282
-
283
-
284
-
285
-/*
286
- *  Build device list for all present ISA PnP devices.
287
- */
288
-static int isapnp_build_device_list(void)
289
-{
290
-	int csn, device, vendor, serial;
291
-	unsigned char header[9], checksum;
292
-	for (csn = 1; csn <= 10; csn++) {
293
-		Wake(csn);
294
-		isapnp_peek(header, 9);
295
-		checksum = isapnp_checksum(header);
296
-#ifdef EDEBUG
297
-		printf
298
-		    ("vendor: 0x%hX:0x%hX:0x%hX:0x%hX:0x%hX:0x%hX:0x%hX:0x%hX:0x%hX\n",
299
-		     header[0], header[1], header[2], header[3], header[4],
300
-		     header[5], header[6], header[7], header[8]);
301
-		printf("checksum = 0xhX\n", checksum);
302
-#endif
303
-		/* Don't be strict on the checksum, here !
304
-		   e.g. 'SCM SwapBox Plug and Play' has header[8]==0 (should be: b7) */
305
-		if (header[8] == 0);
306
-		else if (checksum == 0x00 || checksum != header[8])	/* not valid CSN */
307
-			continue;
308
-
309
-		vendor = (header[1] << 8) | header[0];
310
-		device = (header[3] << 8) | header[2];
311
-		serial =
312
-		    (header[7] << 24) | (header[6] << 16) | (header[5] <<
313
-							     8) |
314
-		    header[4];
315
-		if (vendor == 0x6D50)
316
-			if (device == 0x5150) {
317
-				printf
318
-				    ("\nFound 3Com 3c515 PNP Card!\n Vendor ID: 0x%hX, Device ID: 0x%hX, Serial Num: 0x%hX\n",
319
-				     vendor, device, serial);
320
-				pnp_card_csn = csn;
321
-			}
322
-		isapnp_checksum_value = 0x00;
323
-	}
324
-	return 0;
325
-}
326
-
327
-int Config(int csn)
328
-{
329
-#define TIMEOUT_PNP     100
330
-	unsigned char id[IDENT_LEN];
331
-	int i, x;
332
-	Wake(csn);
333
-	udelay(1000);
334
-	for (i = 0; i < IDENT_LEN; i++) {
335
-		for (x = 1; x < TIMEOUT_PNP; x++) {
336
-			if (STATUS & 1)
337
-				break;
338
-			udelay(1000);
339
-		}
340
-		id[i] = RESOURCEDATA;
341
-#ifdef EDEBUG
342
-		printf(" 0x%hX ", id[i]);
343
-#endif
344
-	}
345
-#ifdef EDEBUG
346
-	printf("Got The status bit\n");
347
-#endif
348
-	/*Set Logical Device Register active */
349
-	LOGICALDEVICENUMBER;
350
-	/* Specify the first logical device */
351
-	WRITE_DATA(0);
352
-
353
-
354
-	/* Apparently just activating the card is enough
355
-	   for Etherboot to detect it.  Why bother with the
356
-	   following code.  Left in place in case it is
357
-	   later required  */
358
-/*==========================================*/
359
-	/* set DMA */
360
-/*    ADDRESS(0x74 + 0);
361
-    WRITE_DATA(7); */
362
-
363
-	/*Set IRQ */
364
-/*    udelay(1000);
365
-    ADDRESS(0x70 + (0 << 1));
366
-    WRITE_DATA(9);
367
-    udelay(1000); */
368
-/*=============================================*/
369
-	/*Activate */
370
-	ACTIVATE;
371
-	WRITE_DATA(1);
372
-	udelay(250);
373
-	/* Ask for access to the Wait for Key command - ConfigControl register */
374
-	CONFIGCONTROL;
375
-	/* Write the Wait for Key Command to the ConfigControl Register */
376
-	WRITE_DATA(CONFIG_WAIT_FOR_KEY);
377
-	/* As per doc. Two Write cycles of 0x00 required befor the Initialization key is sent */
378
-	ADDRESS(0);
379
-	ADDRESS(0);
380
-
381
-	return 1;
382
-}
383
-
384
-
385
-static void isapnp_peek(unsigned char *data, int bytes)
386
-{
387
-	int i, j;
388
-	unsigned char d = 0;
389
-
390
-	for (i = 1; i <= bytes; i++) {
391
-		for (j = 0; j < 20; j++) {
392
-			d = STATUS;
393
-			if (d & 1)
394
-				break;
395
-			udelay(100);
396
-		}
397
-		if (!(d & 1)) {
398
-			if (data != NULL)
399
-				*data++ = 0xff;
400
-			continue;
401
-		}
402
-		d = RESOURCEDATA;	/* PRESDI */
403
-		isapnp_checksum_value += d;
404
-		if (data != NULL)
405
-			*data++ = d;
406
-	}
407
-}
408
-
409
-
410
-
411
-
412
-/*
413
- * Ensure that there is sufficient space in the shared dev_bus
414
- * structure for a struct isapnp_device.
415
- *
416
- */
417
-DEV_BUS( struct isapnp_device, isapnp_dev );
418
-static char isapnp_magic[0]; /* guaranteed unique symbol */
419
-
420 350
 /*
421 351
  * Fill in parameters for an ISAPnP device based on CSN
422 352
  *
@@ -424,23 +354,45 @@ static char isapnp_magic[0]; /* guaranteed unique symbol */
424 354
  *
425 355
  */
426 356
 static int fill_isapnp_device ( struct isapnp_device *isapnp ) {
427
-
428
-	/*
429
-	 * Ensure that all ISAPnP cards have CSNs allocated to them,
357
+	union isapnp_identifier identifier;
358
+	
359
+	/* Ensure that all ISAPnP cards have CSNs allocated to them,
430 360
 	 * if we haven't already done so.
431
-	 *
432 361
 	 */
433 362
 	if ( ! isapnp_read_port ) {
434 363
 		isapnp_isolate();
435 364
 	}
436 365
 
437
-	/* wake csn, read config, send card to sleep */
366
+	/* Wake the specified CSN */
367
+	isapnp_wait_for_key ();
368
+	isapnp_send_key ();
369
+	isapnp_wake ( isapnp->csn );
370
+
371
+	/* Read the identifier and verify the checksum.  Allow
372
+	 * checksum = 0 to cope with cards that just generate the
373
+	 * checksum using the LFSR during serial isolation.
374
+	 */
375
+	isapnp_peek ( identifier.bytes, sizeof ( identifier ) );
376
+	if ( ( identifier.checksum != 0 ) &&
377
+	     ( identifier.checksum != isapnp_checksum ( &identifier ) ) ) {
378
+		DBG ( "ISAPnP invalid checksum on CSN %hhx "
379
+		      "(is %hhx, should be %hhx)\n", isapnp->csn,
380
+		      identifier.checksum, isapnp_checksum ( &identifier ) );
381
+		return 0;
382
+	}
383
+
384
+	/* Read information from identifier structure */
385
+	isapnp->vendor_id = identifier.vendor_id;
386
+	isapnp->prod_id = identifier.prod_id;
387
+
388
+	/* Return all cards to Wait for Key state */
389
+	isapnp_wait_for_key ();
438 390
 
439 391
 	DBG ( "ISAPnP found CSN %hhx ID %hx:%hx (\"%s\")\n",
440 392
 	      isapnp->csn, isapnp->vendor_id, isapnp->prod_id,
441 393
 	      isa_id_string ( isapnp->vendor_id, isapnp->prod_id ) );
442 394
 
443
-	return 0;
395
+	return 1;
444 396
 }
445 397
 
446 398
 /*
@@ -514,3 +466,45 @@ int find_isapnp_boot_device ( struct dev *dev, struct isapnp_driver *driver ) {
514 466
 
515 467
 	return 1;
516 468
 }
469
+
470
+/*
471
+ * Activate a logical function on an ISAPnP device
472
+ *
473
+ * This routine simply activates the device in its current
474
+ * configuration.  It does not attempt any kind of resource
475
+ * arbitration.
476
+ *
477
+ */
478
+void activate_isapnp_device ( struct isapnp_device *isapnp,
479
+			      uint8_t logdev ) {
480
+	/* Wake the device */
481
+	isapnp_wait_for_key ();
482
+	isapnp_send_key ();
483
+	isapnp_wake ( isapnp->csn );
484
+
485
+	/* Select the specified logical device */
486
+	isapnp_activate ( logdev );
487
+	udelay ( 1000 );
488
+	
489
+	/* Return all cards to Wait for Key state */
490
+	isapnp_wait_for_key ();
491
+}
492
+
493
+/*
494
+ * Deactivate a logical function on an ISAPnP device
495
+ *
496
+ */
497
+void deactivate_isapnp_device ( struct isapnp_device *isapnp,
498
+			      uint8_t logdev ) {
499
+	/* Wake the device */
500
+	isapnp_wait_for_key ();
501
+	isapnp_send_key ();
502
+	isapnp_wake ( isapnp->csn );
503
+
504
+	/* Select the specified logical device */
505
+	isapnp_deactivate ( logdev );
506
+	udelay ( 1000 );
507
+	
508
+	/* Return all cards to Wait for Key state */
509
+	isapnp_wait_for_key ();
510
+}

+ 5
- 1
src/include/isapnp.h Ver arquivo

@@ -127,7 +127,7 @@ union isapnp_identifier {
127 127
 	char bytes[9];
128 128
 	struct {
129 129
 		uint16_t vendor_id;
130
-		uint16_t product_id;
130
+		uint16_t prod_id;
131 131
 		uint32_t serial;
132 132
 		uint8_t checksum;
133 133
 	} __attribute__ (( packed ));
@@ -183,5 +183,9 @@ extern int find_isapnp_device ( struct isapnp_device *isapnp,
183 183
 				struct isapnp_driver *driver );
184 184
 extern int find_isapnp_boot_device ( struct dev *dev,
185 185
 				     struct isapnp_driver *driver );
186
+extern void activate_isapnp_device ( struct isapnp_device *isapnp,
187
+				     uint8_t logdev );
188
+extern void deactivate_isapnp_device ( struct isapnp_device *isapnp,
189
+				       uint8_t logdev );
186 190
 
187 191
 #endif /* ISAPNP_H */

Carregando…
Cancelar
Salvar