Bläddra i källkod

We now correctly use logical devices.

tags/v0.9.3
Michael Brown 19 år sedan
förälder
incheckning
e6e43a2f2f
2 ändrade filer med 113 tillägg och 89 borttagningar
  1. 106
    87
      src/drivers/bus/isapnp.c
  2. 7
    2
      src/include/isapnp.h

+ 106
- 87
src/drivers/bus/isapnp.c Visa fil

@@ -190,14 +190,14 @@ static void isapnp_send_key ( void ) {
190 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 194
 	int i, j;
195 195
 	uint8_t lfsr;
196 196
 	uint8_t byte;
197 197
 
198 198
 	lfsr = ISAPNP_LFSR_SEED;
199 199
 	for ( i = 0 ; i < 8 ; i++ ) {
200
-		byte = identifier->bytes[i];
200
+		byte = ( (char *) identifier )[i];
201 201
 		for ( j = 0 ; j < 8 ; j++ ) {
202 202
 			lfsr = isapnp_lfsr_next ( lfsr, byte );
203 203
 			byte >>= 1;
@@ -242,6 +242,38 @@ static void isapnp_peek ( uint8_t *buf, size_t bytes ) {
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 278
  * Try isolating ISAPnP cards at the current read port.  Return the
247 279
  * number of ISAPnP cards found.
@@ -251,7 +283,7 @@ static void isapnp_peek ( uint8_t *buf, size_t bytes ) {
251 283
  *
252 284
  */
253 285
 static int isapnp_try_isolate ( void ) {
254
-	union isapnp_identifier identifier;
286
+	struct isapnp_identifier identifier;
255 287
 	int i, j, seen55aa;
256 288
 	uint16_t data;
257 289
 	uint8_t byte;
@@ -306,7 +338,7 @@ static int isapnp_try_isolate ( void ) {
306 338
 				}
307 339
 				byte <<= 1;
308 340
 			}
309
-			identifier.bytes[i] = byte;
341
+			( (char *) &identifier )[i] = byte;
310 342
 			if ( byte ) {
311 343
 				seen55aa = 1;
312 344
 			}
@@ -319,7 +351,7 @@ static int isapnp_try_isolate ( void ) {
319 351
 
320 352
 		/* Give the device a CSN */
321 353
 		isapnp_max_csn++;
322
-		DBG ( "ISAPnP isolation found device "
354
+		DBG ( "ISAPnP isolation found card "
323 355
 		      "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx "
324 356
 		      "(checksum %hhx), assigning CSN %hhx\n",
325 357
 		      identifier.bytes[0], identifier.bytes[1],
@@ -342,7 +374,7 @@ static int isapnp_try_isolate ( void ) {
342 374
 	isapnp_wait_for_key ();
343 375
 
344 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 378
 	return isapnp_max_csn;
347 379
 }
348 380
 
@@ -374,7 +406,8 @@ static void isapnp_isolate ( void ) {
374 406
  *
375 407
  */
376 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 412
 	/* Ensure that all ISAPnP cards have CSNs allocated to them,
380 413
 	 * if we haven't already done so.
@@ -383,38 +416,42 @@ static int fill_isapnp_device ( struct isapnp_device *isapnp ) {
383 416
 		isapnp_isolate();
384 417
 	}
385 418
 
386
-	/* Wake the specified CSN */
419
+	/* Wake the card */
387 420
 	isapnp_wait_for_key ();
388 421
 	isapnp_send_key ();
389 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 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 447
 	/* Return all cards to Wait for Key state */
413 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 456
 	return 1;
420 457
 }
@@ -438,31 +475,40 @@ int find_isapnp_device ( struct isapnp_device *isapnp,
438 475
 	 * left off.
439 476
 	 */
440 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,8 +538,7 @@ int find_isapnp_boot_device ( struct dev *dev, struct isapnp_driver *driver ) {
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 543
  * This routine simply activates the device in its current
499 544
  * configuration.  It does not attempt any kind of resource
@@ -501,46 +546,20 @@ int find_isapnp_boot_device ( struct dev *dev, struct isapnp_driver *driver ) {
501 546
  *
502 547
  */
503 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 551
 	isapnp_wait_for_key ();
507 552
 	isapnp_send_key ();
508 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 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 560
 	/* Return all cards to Wait for Key state */
542 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 Visa fil

@@ -81,7 +81,10 @@
81 81
 /* The LFSR used for the initiation key and for checksumming */
82 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 88
 #define ISAPNP_TAG_PNPVERNO		0x01
86 89
 #define ISAPNP_TAG_LOGDEVID		0x02
87 90
 #define ISAPNP_TAG_COMPATDEVID		0x03
@@ -97,7 +100,9 @@
97 100
 #define ISAPNP_TAG_RSVDSHORTD		0x0D
98 101
 #define ISAPNP_TAG_VENDORSHORT		0x0E
99 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 106
 #define ISAPNP_TAG_MEMRANGE		0x81
102 107
 #define ISAPNP_TAG_ANSISTR		0x82
103 108
 #define ISAPNP_TAG_UNICODESTR		0x83

Laddar…
Avbryt
Spara