|  | @@ -25,6 +25,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 | 
		
	
		
			
			| 25 | 25 |  
 | 
		
	
		
			
			| 26 | 26 |  #include <string.h>
 | 
		
	
		
			
			| 27 | 27 |  #include <strings.h>
 | 
		
	
		
			
			|  | 28 | +#include <stdlib.h>
 | 
		
	
		
			
			| 28 | 29 |  #include <unistd.h>
 | 
		
	
		
			
			| 29 | 30 |  #include <errno.h>
 | 
		
	
		
			
			| 30 | 31 |  #include <ipxe/netdevice.h>
 | 
		
	
	
		
			
			|  | @@ -137,6 +138,16 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 | 
		
	
		
			
			| 137 | 138 |   */
 | 
		
	
		
			
			| 138 | 139 |  #define PCI_MAX_BAR 6
 | 
		
	
		
			
			| 139 | 140 |  
 | 
		
	
		
			
			|  | 141 | +/** An NII memory mapping */
 | 
		
	
		
			
			|  | 142 | +struct nii_mapping {
 | 
		
	
		
			
			|  | 143 | +	/** List of mappings */
 | 
		
	
		
			
			|  | 144 | +	struct list_head list;
 | 
		
	
		
			
			|  | 145 | +	/** Mapped address */
 | 
		
	
		
			
			|  | 146 | +	UINT64 addr;
 | 
		
	
		
			
			|  | 147 | +	/** Mapping cookie created by PCI I/O protocol */
 | 
		
	
		
			
			|  | 148 | +	VOID *mapping;
 | 
		
	
		
			
			|  | 149 | +};
 | 
		
	
		
			
			|  | 150 | +
 | 
		
	
		
			
			| 140 | 151 |  /** An NII NIC */
 | 
		
	
		
			
			| 141 | 152 |  struct nii_nic {
 | 
		
	
		
			
			| 142 | 153 |  	/** EFI device */
 | 
		
	
	
		
			
			|  | @@ -179,6 +190,9 @@ struct nii_nic {
 | 
		
	
		
			
			| 179 | 190 |  	struct io_buffer *txbuf;
 | 
		
	
		
			
			| 180 | 191 |  	/** Current receive buffer */
 | 
		
	
		
			
			| 181 | 192 |  	struct io_buffer *rxbuf;
 | 
		
	
		
			
			|  | 193 | +
 | 
		
	
		
			
			|  | 194 | +	/** Mapping list */
 | 
		
	
		
			
			|  | 195 | +	struct list_head mappings;
 | 
		
	
		
			
			| 182 | 196 |  };
 | 
		
	
		
			
			| 183 | 197 |  
 | 
		
	
		
			
			| 184 | 198 |  /** Maximum number of received packets per poll */
 | 
		
	
	
		
			
			|  | @@ -280,7 +294,19 @@ static int nii_pci_open ( struct nii_nic *nii ) {
 | 
		
	
		
			
			| 280 | 294 |   */
 | 
		
	
		
			
			| 281 | 295 |  static void nii_pci_close ( struct nii_nic *nii ) {
 | 
		
	
		
			
			| 282 | 296 |  	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
 | 
		
	
		
			
			|  | 297 | +	struct nii_mapping *map;
 | 
		
	
		
			
			|  | 298 | +	struct nii_mapping *tmp;
 | 
		
	
		
			
			|  | 299 | +
 | 
		
	
		
			
			|  | 300 | +	/* Remove any stale mappings */
 | 
		
	
		
			
			|  | 301 | +	list_for_each_entry_safe ( map, tmp, &nii->mappings, list ) {
 | 
		
	
		
			
			|  | 302 | +		DBGC ( nii, "NII %s removing stale mapping %#llx\n",
 | 
		
	
		
			
			|  | 303 | +		       nii->dev.name, ( ( unsigned long long ) map->addr ) );
 | 
		
	
		
			
			|  | 304 | +		nii->pci_io->Unmap ( nii->pci_io, map->mapping );
 | 
		
	
		
			
			|  | 305 | +		list_del ( &map->list );
 | 
		
	
		
			
			|  | 306 | +		free ( map );
 | 
		
	
		
			
			|  | 307 | +	}
 | 
		
	
		
			
			| 283 | 308 |  
 | 
		
	
		
			
			|  | 309 | +	/* Close protocols */
 | 
		
	
		
			
			| 284 | 310 |  	bs->CloseProtocol ( nii->pci_device, &efi_pci_io_protocol_guid,
 | 
		
	
		
			
			| 285 | 311 |  			    efi_image_handle, nii->efidev->device );
 | 
		
	
		
			
			| 286 | 312 |  }
 | 
		
	
	
		
			
			|  | @@ -331,6 +357,139 @@ static EFIAPI VOID nii_io ( UINT64 unique_id, UINT8 op, UINT8 len, UINT64 addr,
 | 
		
	
		
			
			| 331 | 357 |  	}
 | 
		
	
		
			
			| 332 | 358 |  }
 | 
		
	
		
			
			| 333 | 359 |  
 | 
		
	
		
			
			|  | 360 | +/**
 | 
		
	
		
			
			|  | 361 | + * Map callback
 | 
		
	
		
			
			|  | 362 | + *
 | 
		
	
		
			
			|  | 363 | + * @v unique_id		NII NIC
 | 
		
	
		
			
			|  | 364 | + * @v addr		Address of memory to be mapped
 | 
		
	
		
			
			|  | 365 | + * @v len		Length of memory to be mapped
 | 
		
	
		
			
			|  | 366 | + * @v dir		Direction of data flow
 | 
		
	
		
			
			|  | 367 | + * @v mapped		Device mapped address to fill in
 | 
		
	
		
			
			|  | 368 | + */
 | 
		
	
		
			
			|  | 369 | +static EFIAPI VOID nii_map ( UINT64 unique_id, UINT64 addr, UINT32 len,
 | 
		
	
		
			
			|  | 370 | +			     UINT32 dir, UINT64 mapped ) {
 | 
		
	
		
			
			|  | 371 | +	struct nii_nic *nii = ( ( void * ) ( intptr_t ) unique_id );
 | 
		
	
		
			
			|  | 372 | +	EFI_PHYSICAL_ADDRESS *phys = ( ( void * ) ( intptr_t ) mapped );
 | 
		
	
		
			
			|  | 373 | +	EFI_PCI_IO_PROTOCOL_OPERATION op;
 | 
		
	
		
			
			|  | 374 | +	struct nii_mapping *map;
 | 
		
	
		
			
			|  | 375 | +	UINTN count = len;
 | 
		
	
		
			
			|  | 376 | +	EFI_STATUS efirc;
 | 
		
	
		
			
			|  | 377 | +	int rc;
 | 
		
	
		
			
			|  | 378 | +
 | 
		
	
		
			
			|  | 379 | +	/* Return a zero mapped address on failure */
 | 
		
	
		
			
			|  | 380 | +	*phys = 0;
 | 
		
	
		
			
			|  | 381 | +
 | 
		
	
		
			
			|  | 382 | +	/* Determine PCI mapping operation */
 | 
		
	
		
			
			|  | 383 | +	switch ( dir ) {
 | 
		
	
		
			
			|  | 384 | +	case TO_AND_FROM_DEVICE:
 | 
		
	
		
			
			|  | 385 | +		op = EfiPciIoOperationBusMasterCommonBuffer;
 | 
		
	
		
			
			|  | 386 | +		break;
 | 
		
	
		
			
			|  | 387 | +	case FROM_DEVICE:
 | 
		
	
		
			
			|  | 388 | +		op = EfiPciIoOperationBusMasterWrite;
 | 
		
	
		
			
			|  | 389 | +		break;
 | 
		
	
		
			
			|  | 390 | +	case TO_DEVICE:
 | 
		
	
		
			
			|  | 391 | +		op = EfiPciIoOperationBusMasterRead;
 | 
		
	
		
			
			|  | 392 | +		break;
 | 
		
	
		
			
			|  | 393 | +	default:
 | 
		
	
		
			
			|  | 394 | +		DBGC ( nii, "NII %s unsupported mapping direction %d\n",
 | 
		
	
		
			
			|  | 395 | +		       nii->dev.name, dir );
 | 
		
	
		
			
			|  | 396 | +		goto err_dir;
 | 
		
	
		
			
			|  | 397 | +	}
 | 
		
	
		
			
			|  | 398 | +
 | 
		
	
		
			
			|  | 399 | +	/* Allocate a mapping record */
 | 
		
	
		
			
			|  | 400 | +	map = zalloc ( sizeof ( *map ) );
 | 
		
	
		
			
			|  | 401 | +	if ( ! map )
 | 
		
	
		
			
			|  | 402 | +		goto err_alloc;
 | 
		
	
		
			
			|  | 403 | +	map->addr = addr;
 | 
		
	
		
			
			|  | 404 | +
 | 
		
	
		
			
			|  | 405 | +	/* Create map */
 | 
		
	
		
			
			|  | 406 | +	if ( ( efirc = nii->pci_io->Map ( nii->pci_io, op,
 | 
		
	
		
			
			|  | 407 | +					  ( ( void * ) ( intptr_t ) addr ),
 | 
		
	
		
			
			|  | 408 | +					  &count, phys, &map->mapping ) ) != 0){
 | 
		
	
		
			
			|  | 409 | +		rc = -EEFI ( efirc );
 | 
		
	
		
			
			|  | 410 | +		DBGC ( nii, "NII %s map operation failed: %s\n",
 | 
		
	
		
			
			|  | 411 | +		       nii->dev.name, strerror ( rc ) );
 | 
		
	
		
			
			|  | 412 | +		goto err_map;
 | 
		
	
		
			
			|  | 413 | +	}
 | 
		
	
		
			
			|  | 414 | +
 | 
		
	
		
			
			|  | 415 | +	/* Add to list of mappings */
 | 
		
	
		
			
			|  | 416 | +	list_add ( &map->list, &nii->mappings );
 | 
		
	
		
			
			|  | 417 | +	DBGC2 ( nii, "NII %s mapped %#llx+%#x->%#llx\n",
 | 
		
	
		
			
			|  | 418 | +		nii->dev.name, ( ( unsigned long long ) addr ),
 | 
		
	
		
			
			|  | 419 | +		len, ( ( unsigned long long ) *phys ) );
 | 
		
	
		
			
			|  | 420 | +	return;
 | 
		
	
		
			
			|  | 421 | +
 | 
		
	
		
			
			|  | 422 | +	list_del ( &map->list );
 | 
		
	
		
			
			|  | 423 | + err_map:
 | 
		
	
		
			
			|  | 424 | +	free ( map );
 | 
		
	
		
			
			|  | 425 | + err_alloc:
 | 
		
	
		
			
			|  | 426 | + err_dir:
 | 
		
	
		
			
			|  | 427 | +	return;
 | 
		
	
		
			
			|  | 428 | +}
 | 
		
	
		
			
			|  | 429 | +
 | 
		
	
		
			
			|  | 430 | +/**
 | 
		
	
		
			
			|  | 431 | + * Unmap callback
 | 
		
	
		
			
			|  | 432 | + *
 | 
		
	
		
			
			|  | 433 | + * @v unique_id		NII NIC
 | 
		
	
		
			
			|  | 434 | + * @v addr		Address of mapped memory
 | 
		
	
		
			
			|  | 435 | + * @v len		Length of mapped memory
 | 
		
	
		
			
			|  | 436 | + * @v dir		Direction of data flow
 | 
		
	
		
			
			|  | 437 | + * @v mapped		Device mapped address
 | 
		
	
		
			
			|  | 438 | + */
 | 
		
	
		
			
			|  | 439 | +static EFIAPI VOID nii_unmap ( UINT64 unique_id, UINT64 addr, UINT32 len,
 | 
		
	
		
			
			|  | 440 | +			       UINT32 dir __unused, UINT64 mapped ) {
 | 
		
	
		
			
			|  | 441 | +	struct nii_nic *nii = ( ( void * ) ( intptr_t ) unique_id );
 | 
		
	
		
			
			|  | 442 | +	struct nii_mapping *map;
 | 
		
	
		
			
			|  | 443 | +
 | 
		
	
		
			
			|  | 444 | +	/* Locate mapping record */
 | 
		
	
		
			
			|  | 445 | +	list_for_each_entry ( map, &nii->mappings, list ) {
 | 
		
	
		
			
			|  | 446 | +		if ( map->addr == addr ) {
 | 
		
	
		
			
			|  | 447 | +			nii->pci_io->Unmap ( nii->pci_io, map->mapping );
 | 
		
	
		
			
			|  | 448 | +			list_del ( &map->list );
 | 
		
	
		
			
			|  | 449 | +			free ( map );
 | 
		
	
		
			
			|  | 450 | +			DBGC2 ( nii, "NII %s unmapped %#llx+%#x->%#llx\n",
 | 
		
	
		
			
			|  | 451 | +				nii->dev.name, ( ( unsigned long long ) addr ),
 | 
		
	
		
			
			|  | 452 | +				len, ( ( unsigned long long ) mapped ) );
 | 
		
	
		
			
			|  | 453 | +			return;
 | 
		
	
		
			
			|  | 454 | +		}
 | 
		
	
		
			
			|  | 455 | +	}
 | 
		
	
		
			
			|  | 456 | +
 | 
		
	
		
			
			|  | 457 | +	DBGC ( nii, "NII %s non-existent mapping %#llx+%#x->%#llx\n",
 | 
		
	
		
			
			|  | 458 | +	       nii->dev.name, ( ( unsigned long long ) addr ),
 | 
		
	
		
			
			|  | 459 | +	       len, ( ( unsigned long long ) mapped ) );
 | 
		
	
		
			
			|  | 460 | +}
 | 
		
	
		
			
			|  | 461 | +
 | 
		
	
		
			
			|  | 462 | +/**
 | 
		
	
		
			
			|  | 463 | + * Sync callback
 | 
		
	
		
			
			|  | 464 | + *
 | 
		
	
		
			
			|  | 465 | + * @v unique_id		NII NIC
 | 
		
	
		
			
			|  | 466 | + * @v addr		Address of mapped memory
 | 
		
	
		
			
			|  | 467 | + * @v len		Length of mapped memory
 | 
		
	
		
			
			|  | 468 | + * @v dir		Direction of data flow
 | 
		
	
		
			
			|  | 469 | + * @v mapped		Device mapped address
 | 
		
	
		
			
			|  | 470 | + */
 | 
		
	
		
			
			|  | 471 | +static EFIAPI VOID nii_sync ( UINT64 unique_id __unused, UINT64 addr,
 | 
		
	
		
			
			|  | 472 | +			      UINT32 len, UINT32 dir, UINT64 mapped ) {
 | 
		
	
		
			
			|  | 473 | +	const void *src;
 | 
		
	
		
			
			|  | 474 | +	void *dst;
 | 
		
	
		
			
			|  | 475 | +
 | 
		
	
		
			
			|  | 476 | +	/* Do nothing if this is an identity mapping */
 | 
		
	
		
			
			|  | 477 | +	if ( addr == mapped )
 | 
		
	
		
			
			|  | 478 | +		return;
 | 
		
	
		
			
			|  | 479 | +
 | 
		
	
		
			
			|  | 480 | +	/* Determine direction */
 | 
		
	
		
			
			|  | 481 | +	if ( dir == FROM_DEVICE ) {
 | 
		
	
		
			
			|  | 482 | +		src = ( ( void * ) ( intptr_t ) mapped );
 | 
		
	
		
			
			|  | 483 | +		dst = ( ( void * ) ( intptr_t ) addr );
 | 
		
	
		
			
			|  | 484 | +	} else {
 | 
		
	
		
			
			|  | 485 | +		src = ( ( void * ) ( intptr_t ) addr );
 | 
		
	
		
			
			|  | 486 | +		dst = ( ( void * ) ( intptr_t ) mapped );
 | 
		
	
		
			
			|  | 487 | +	}
 | 
		
	
		
			
			|  | 488 | +
 | 
		
	
		
			
			|  | 489 | +	/* Copy data */
 | 
		
	
		
			
			|  | 490 | +	memcpy ( dst, src, len );
 | 
		
	
		
			
			|  | 491 | +}
 | 
		
	
		
			
			|  | 492 | +
 | 
		
	
		
			
			| 334 | 493 |  /**
 | 
		
	
		
			
			| 335 | 494 |   * Delay callback
 | 
		
	
		
			
			| 336 | 495 |   *
 | 
		
	
	
		
			
			|  | @@ -499,6 +658,9 @@ static int nii_start_undi ( struct nii_nic *nii ) {
 | 
		
	
		
			
			| 499 | 658 |  	cpb.Delay = ( ( intptr_t ) nii_delay );
 | 
		
	
		
			
			| 500 | 659 |  	cpb.Block = ( ( intptr_t ) nii_block );
 | 
		
	
		
			
			| 501 | 660 |  	cpb.Mem_IO = ( ( intptr_t ) nii_io );
 | 
		
	
		
			
			|  | 661 | +	cpb.Map_Mem = ( ( intptr_t ) nii_map );
 | 
		
	
		
			
			|  | 662 | +	cpb.UnMap_Mem = ( ( intptr_t ) nii_unmap );
 | 
		
	
		
			
			|  | 663 | +	cpb.Sync_Mem = ( ( intptr_t ) nii_sync );
 | 
		
	
		
			
			| 502 | 664 |  	cpb.Unique_ID = ( ( intptr_t ) nii );
 | 
		
	
		
			
			| 503 | 665 |  
 | 
		
	
		
			
			| 504 | 666 |  	/* Issue command */
 | 
		
	
	
		
			
			|  | @@ -1063,6 +1225,7 @@ int nii_start ( struct efi_device *efidev ) {
 | 
		
	
		
			
			| 1063 | 1225 |  	netdev_init ( netdev, &nii_operations );
 | 
		
	
		
			
			| 1064 | 1226 |  	nii = netdev->priv;
 | 
		
	
		
			
			| 1065 | 1227 |  	nii->efidev = efidev;
 | 
		
	
		
			
			|  | 1228 | +	INIT_LIST_HEAD ( &nii->mappings );
 | 
		
	
		
			
			| 1066 | 1229 |  	netdev->ll_broadcast = nii->broadcast;
 | 
		
	
		
			
			| 1067 | 1230 |  	efidev_set_drvdata ( efidev, netdev );
 | 
		
	
		
			
			| 1068 | 1231 |  
 |