Browse Source

We now correctly use logical devices.

tags/v0.9.3
Michael Brown 19 years ago
parent
commit
e6e43a2f2f
2 changed files with 113 additions and 89 deletions
  1. 106
    87
      src/drivers/bus/isapnp.c
  2. 7
    2
      src/include/isapnp.h

+ 106
- 87
src/drivers/bus/isapnp.c View File

190
  *  Compute ISAPnP identifier checksum
190
  *  Compute ISAPnP identifier checksum
191
  *
191
  *
192
  */
192
  */
193
-static uint8_t isapnp_checksum ( union isapnp_identifier *identifier ) {
193
+static uint8_t isapnp_checksum ( struct isapnp_identifier *identifier ) {
194
 	int i, j;
194
 	int i, j;
195
 	uint8_t lfsr;
195
 	uint8_t lfsr;
196
 	uint8_t byte;
196
 	uint8_t byte;
197
 
197
 
198
 	lfsr = ISAPNP_LFSR_SEED;
198
 	lfsr = ISAPNP_LFSR_SEED;
199
 	for ( i = 0 ; i < 8 ; i++ ) {
199
 	for ( i = 0 ; i < 8 ; i++ ) {
200
-		byte = identifier->bytes[i];
200
+		byte = ( (char *) identifier )[i];
201
 		for ( j = 0 ; j < 8 ; j++ ) {
201
 		for ( j = 0 ; j < 8 ; j++ ) {
202
 			lfsr = isapnp_lfsr_next ( lfsr, byte );
202
 			lfsr = isapnp_lfsr_next ( lfsr, byte );
203
 			byte >>= 1;
203
 			byte >>= 1;
242
 	}
242
 	}
243
 }
243
 }
244
 
244
 
245
+/*
246
+ * Scan through the resource data until we find a particular tag, and
247
+ * read its contents into a buffer.
248
+ *
249
+ * It is the caller's responsibility to ensure that buf is large
250
+ * enough to contain a tag of the requested size.
251
+ *
252
+ */
253
+static int isapnp_find_tag ( uint8_t wanted_tag, uint8_t *buf ) {
254
+	uint8_t tag;
255
+	uint16_t len;
256
+
257
+	do {
258
+		tag = isapnp_peek_byte();
259
+		if ( ISAPNP_IS_SMALL_TAG ( tag ) ) {
260
+			len = ISAPNP_SMALL_TAG_LEN ( tag );
261
+			tag = ISAPNP_SMALL_TAG_NAME ( tag );
262
+		} else {
263
+			len = isapnp_peek_byte() + ( isapnp_peek_byte() << 8 );
264
+			tag = ISAPNP_LARGE_TAG_NAME ( tag );
265
+		}
266
+		DBG ( "ISAPnP read tag %hhx len %hhx\n", tag, len );
267
+		if ( tag == wanted_tag ) {
268
+			isapnp_peek ( buf, len );
269
+			return 1;
270
+		} else {
271
+			isapnp_peek ( NULL, len );
272
+		}
273
+	} while ( tag != ISAPNP_TAG_END );
274
+	return 0;
275
+}
276
+
245
 /*
277
 /*
246
  * Try isolating ISAPnP cards at the current read port.  Return the
278
  * Try isolating ISAPnP cards at the current read port.  Return the
247
  * number of ISAPnP cards found.
279
  * number of ISAPnP cards found.
251
  *
283
  *
252
  */
284
  */
253
 static int isapnp_try_isolate ( void ) {
285
 static int isapnp_try_isolate ( void ) {
254
-	union isapnp_identifier identifier;
286
+	struct isapnp_identifier identifier;
255
 	int i, j, seen55aa;
287
 	int i, j, seen55aa;
256
 	uint16_t data;
288
 	uint16_t data;
257
 	uint8_t byte;
289
 	uint8_t byte;
306
 				}
338
 				}
307
 				byte <<= 1;
339
 				byte <<= 1;
308
 			}
340
 			}
309
-			identifier.bytes[i] = byte;
341
+			( (char *) &identifier )[i] = byte;
310
 			if ( byte ) {
342
 			if ( byte ) {
311
 				seen55aa = 1;
343
 				seen55aa = 1;
312
 			}
344
 			}
319
 
351
 
320
 		/* Give the device a CSN */
352
 		/* Give the device a CSN */
321
 		isapnp_max_csn++;
353
 		isapnp_max_csn++;
322
-		DBG ( "ISAPnP isolation found device "
354
+		DBG ( "ISAPnP isolation found card "
323
 		      "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx "
355
 		      "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx "
324
 		      "(checksum %hhx), assigning CSN %hhx\n",
356
 		      "(checksum %hhx), assigning CSN %hhx\n",
325
 		      identifier.bytes[0], identifier.bytes[1],
357
 		      identifier.bytes[0], identifier.bytes[1],
342
 	isapnp_wait_for_key ();
374
 	isapnp_wait_for_key ();
343
 
375
 
344
 	/* Return number of cards found */
376
 	/* Return number of cards found */
345
-	DBG ( "ISAPnP found %d devices at read port %hx\n", isapnp_read_port );
377
+	DBG ( "ISAPnP found %d cards at read port %hx\n", isapnp_read_port );
346
 	return isapnp_max_csn;
378
 	return isapnp_max_csn;
347
 }
379
 }
348
 
380
 
374
  *
406
  *
375
  */
407
  */
376
 static int fill_isapnp_device ( struct isapnp_device *isapnp ) {
408
 static int fill_isapnp_device ( struct isapnp_device *isapnp ) {
377
-	union isapnp_identifier identifier;
409
+	unsigned int i;
410
+	struct isapnp_logdevid logdevid;
378
 	
411
 	
379
 	/* Ensure that all ISAPnP cards have CSNs allocated to them,
412
 	/* Ensure that all ISAPnP cards have CSNs allocated to them,
380
 	 * if we haven't already done so.
413
 	 * if we haven't already done so.
383
 		isapnp_isolate();
416
 		isapnp_isolate();
384
 	}
417
 	}
385
 
418
 
386
-	/* Wake the specified CSN */
419
+	/* Wake the card */
387
 	isapnp_wait_for_key ();
420
 	isapnp_wait_for_key ();
388
 	isapnp_send_key ();
421
 	isapnp_send_key ();
389
 	isapnp_wake ( isapnp->csn );
422
 	isapnp_wake ( isapnp->csn );
390
 
423
 
391
-	/* Read the identifier.  Do *not* verify the checksum, because
392
-	 * the PnP ISA spec explicitly states in section 4.5 that the
393
-	 * checksum is invalid except when read via the serial
394
-	 * isolation protocol.  (This is presumably to allow for lazy
395
-	 * card designers who implement the checksum using the LFSR
396
-	 * only and can't be bothered to write the same value into the
397
-	 * EPROM).
398
-	 */
399
-	isapnp_peek ( identifier.bytes, sizeof ( identifier ) );
424
+	/* Skip past the card identifier */
425
+	isapnp_peek ( NULL, sizeof ( struct isapnp_identifier ) );
426
+
427
+	/* Find the Logical Device ID tag corresponding to this device */
428
+	for ( i = 0 ; i <= isapnp->logdev ; i++ ) {
429
+		if ( ! isapnp_find_tag ( ISAPNP_TAG_LOGDEVID,
430
+					 ( char * ) &logdevid ) ) {
431
+			/* No tag for this device */
432
+			return 0;
433
+		}
434
+	}
400
 
435
 
401
 	/* Read information from identifier structure */
436
 	/* Read information from identifier structure */
402
-	isapnp->vendor_id = identifier.vendor_id;
403
-	isapnp->prod_id = identifier.prod_id;
437
+	isapnp->vendor_id = logdevid.vendor_id;
438
+	isapnp->prod_id = logdevid.prod_id;
404
 
439
 
405
-	/* I/O addresses and IRQs are associated with logical devices,
406
-	 * not with cards.  They will be assigned when
407
-	 * activate_isapnp_device() is called.
408
-	 */
409
-	isapnp->ioaddr = 0;
410
-	isapnp->irqno = 0;
440
+	/* Select the logical device */
441
+	isapnp_logicaldevice ( isapnp->logdev );
442
+
443
+	/* Read the current ioaddr and irqno */
444
+	isapnp->ioaddr = isapnp_read_iobase ( 0 );
445
+	isapnp->irqno = isapnp_read_irqno ( 0 );
411
 
446
 
412
 	/* Return all cards to Wait for Key state */
447
 	/* Return all cards to Wait for Key state */
413
 	isapnp_wait_for_key ();
448
 	isapnp_wait_for_key ();
414
 
449
 
415
-	DBG ( "ISAPnP found CSN %hhx ID %hx:%hx (\"%s\")\n",
416
-	      isapnp->csn, isapnp->vendor_id, isapnp->prod_id,
417
-	      isa_id_string ( isapnp->vendor_id, isapnp->prod_id ) );
450
+	DBG ( "ISAPnP found device %hhx.%hhx ID %hx:%hx (\"%s\"), "
451
+	      "base %hx irq %d\n",
452
+	      isapnp->csn, isapnp->logdev, isapnp->vendor_id, isapnp->prod_id,
453
+	      isa_id_string ( isapnp->vendor_id, isapnp->prod_id ),
454
+	      isapnp->ioaddr, isapnp->irqno );
418
 
455
 
419
 	return 1;
456
 	return 1;
420
 }
457
 }
438
 	 * left off.
475
 	 * left off.
439
 	 */
476
 	 */
440
 	for ( ; isapnp->csn <= isapnp_max_csn ; isapnp->csn++ ) {
477
 	for ( ; isapnp->csn <= isapnp_max_csn ; isapnp->csn++ ) {
441
-		/* If we've already used this device, skip it */
442
-		if ( isapnp->already_tried ) {
443
-			isapnp->already_tried = 0;
444
-			continue;
445
-		}
446
-
447
-		/* Fill in device parameters */
448
-		if ( ! fill_isapnp_device ( isapnp ) ) {
449
-			continue;
450
-		}
451
-
452
-		/* Compare against driver's ID list */
453
-		for ( i = 0 ; i < driver->id_count ; i++ ) {
454
-			struct isapnp_id *id = &driver->ids[i];
478
+		for ( ; isapnp->logdev <= 0xff ; isapnp->logdev++ ) {
479
+			/* If we've already used this device, skip it */
480
+			if ( isapnp->already_tried ) {
481
+				isapnp->already_tried = 0;
482
+				continue;
483
+			}
455
 			
484
 			
456
-			if ( ( isapnp->vendor_id == id->vendor_id ) &&
457
-			     ( ISA_PROD_ID ( isapnp->prod_id ) ==
458
-			       ISA_PROD_ID ( id->prod_id ) ) ) {
459
-				DBG ( "Device %s (driver %s) matches ID %s\n",
460
-				      id->name, driver->name,
461
-				      isa_id_string ( isapnp->vendor_id,
462
-						      isapnp->prod_id ) );
463
-				isapnp->name = id->name;
464
-				isapnp->already_tried = 1;
465
-				return 1;
485
+			/* Fill in device parameters */
486
+			if ( ! fill_isapnp_device ( isapnp ) ) {
487
+				/* If fill_isapnp_device fails, assume
488
+				 * that we've reached the last logical
489
+				 * device on this card, and proceed to
490
+				 * the next card.
491
+				 */
492
+				isapnp->logdev = 0;
493
+				break;
494
+			}
495
+
496
+			/* Compare against driver's ID list */
497
+			for ( i = 0 ; i < driver->id_count ; i++ ) {
498
+				struct isapnp_id *id = &driver->ids[i];
499
+				
500
+				if ( ( isapnp->vendor_id == id->vendor_id ) &&
501
+				     ( ISA_PROD_ID ( isapnp->prod_id ) ==
502
+				       ISA_PROD_ID ( id->prod_id ) ) ) {
503
+					DBG ( "Device %s (driver %s) "
504
+					      "matches ID %s\n",
505
+					      id->name, driver->name,
506
+					      isa_id_string( isapnp->vendor_id,
507
+							   isapnp->prod_id ) );
508
+					isapnp->name = id->name;
509
+					isapnp->already_tried = 1;
510
+					return 1;
511
+				}
466
 			}
512
 			}
467
 		}
513
 		}
468
 	}
514
 	}
492
 }
538
 }
493
 
539
 
494
 /*
540
 /*
495
- * Activate a logical function on an ISAPnP device, and fill in the
496
- * ioaddr and irqno fields in the isapnp struct.
541
+ * Activate or deactivate an ISAPnP device
497
  *
542
  *
498
  * This routine simply activates the device in its current
543
  * This routine simply activates the device in its current
499
  * configuration.  It does not attempt any kind of resource
544
  * configuration.  It does not attempt any kind of resource
501
  *
546
  *
502
  */
547
  */
503
 void activate_isapnp_device ( struct isapnp_device *isapnp,
548
 void activate_isapnp_device ( struct isapnp_device *isapnp,
504
-			      uint8_t logdev ) {
505
-	/* Wake the device */
549
+			      int activate ) {
550
+	/* Wake the card and select the logical device */
506
 	isapnp_wait_for_key ();
551
 	isapnp_wait_for_key ();
507
 	isapnp_send_key ();
552
 	isapnp_send_key ();
508
 	isapnp_wake ( isapnp->csn );
553
 	isapnp_wake ( isapnp->csn );
554
+	isapnp_logicaldevice ( isapnp->logdev );
509
 
555
 
510
-	/* Select the specified logical device */
511
-	isapnp_activate ( logdev );
556
+	/* Activate/deactivate the logical device */
557
+	isapnp_activate ( activate );
512
 	isapnp_delay();
558
 	isapnp_delay();
513
 
559
 
514
-	/* Read the current ioaddr and irqno */
515
-	isapnp->ioaddr = isapnp_read_iobase ( 0 );
516
-	isapnp->irqno = isapnp_read_irqno ( 0 );
517
-	
518
-	/* Return all cards to Wait for Key state */
519
-	isapnp_wait_for_key ();
520
-
521
-	DBG ( "ISAPnP activated logical device %hhx on CSN %hhx "
522
-	      "with ioaddr %hx and IRQ %d\n",
523
-	      logdev, isapnp->csn, isapnp->ioaddr, isapnp->irqno );
524
-}
525
-
526
-/*
527
- * Deactivate a logical function on an ISAPnP device
528
- *
529
- */
530
-void deactivate_isapnp_device ( struct isapnp_device *isapnp,
531
-				uint8_t logdev ) {
532
-	/* Wake the device */
533
-	isapnp_wait_for_key ();
534
-	isapnp_send_key ();
535
-	isapnp_wake ( isapnp->csn );
536
-
537
-	/* Select the specified logical device */
538
-	isapnp_deactivate ( logdev );
539
-	isapnp_delay();
540
-	
541
 	/* Return all cards to Wait for Key state */
560
 	/* Return all cards to Wait for Key state */
542
 	isapnp_wait_for_key ();
561
 	isapnp_wait_for_key ();
543
 
562
 
544
-	DBG ( "ISAPnP deactivated logical device %hhx on CSN %hhx\n",
545
-	      logdev, isapnp->csn );
563
+	DBG ( "ISAPnP activated device %hhx.%hhx\n",
564
+	      isapnp->csn, isapnp->logdev );
546
 }
565
 }

+ 7
- 2
src/include/isapnp.h View File

81
 /* The LFSR used for the initiation key and for checksumming */
81
 /* The LFSR used for the initiation key and for checksumming */
82
 #define ISAPNP_LFSR_SEED		0x6a
82
 #define ISAPNP_LFSR_SEED		0x6a
83
 
83
 
84
-/* Short  Tags */
84
+/* Small tags */
85
+#define ISAPNP_IS_SMALL_TAG(tag)	( ! ( (tag) & 0x80 ) )
86
+#define ISAPNP_SMALL_TAG_NAME(tag)	( ( (tag) >> 3 ) & 0xf )
87
+#define ISAPNP_SMALL_TAG_LEN(tag)	( ( (tag) & 0x7 ) )
85
 #define ISAPNP_TAG_PNPVERNO		0x01
88
 #define ISAPNP_TAG_PNPVERNO		0x01
86
 #define ISAPNP_TAG_LOGDEVID		0x02
89
 #define ISAPNP_TAG_LOGDEVID		0x02
87
 #define ISAPNP_TAG_COMPATDEVID		0x03
90
 #define ISAPNP_TAG_COMPATDEVID		0x03
97
 #define ISAPNP_TAG_RSVDSHORTD		0x0D
100
 #define ISAPNP_TAG_RSVDSHORTD		0x0D
98
 #define ISAPNP_TAG_VENDORSHORT		0x0E
101
 #define ISAPNP_TAG_VENDORSHORT		0x0E
99
 #define ISAPNP_TAG_END			0x0F
102
 #define ISAPNP_TAG_END			0x0F
100
-/* Long  Tags */
103
+/* Large tags */
104
+#define ISAPNP_IS_LARGE_TAG(tag)	( ( (tag) & 0x80 ) )
105
+#define ISAPNP_LARGE_TAG_NAME(tag)	( (tag) & 0x7f )
101
 #define ISAPNP_TAG_MEMRANGE		0x81
106
 #define ISAPNP_TAG_MEMRANGE		0x81
102
 #define ISAPNP_TAG_ANSISTR		0x82
107
 #define ISAPNP_TAG_ANSISTR		0x82
103
 #define ISAPNP_TAG_UNICODESTR		0x83
108
 #define ISAPNP_TAG_UNICODESTR		0x83

Loading…
Cancel
Save