/* * Macro: PCI_WRITE_CONFIG_BYTE * Arguments: %eax address to write to (includes bus, device, function, &offset) * %dl byte to write * * Results: none * * Trashed: %eax, %edx * Effects: writes a single byte to pci config space * * Notes: This routine is optimized for minimal register usage. * And the tricks it does cannot scale beyond writing a single byte. * * What it does is almost simple. * It preserves %eax (baring special bits) until it is written * out to the appropriate port. And hides the data byte * in the high half of edx. * * In %edx[3] it stores the byte to write. * In %edx[2] it stores the lower three bits of the address. */ #define PCI_WRITE_CONFIG_BYTE \ shll $8, %edx ; \ movb %al, %dl ; \ andb $0x3, %dl ; \ shll $16, %edx ; \ \ orl $0x80000000, %eax ; \ andl $0xfffffffc, %eax ; \ movw $0xcf8, %dx ; \ outl %eax, %dx ; \ \ shrl $16, %edx ; \ movb %dh, %al ; \ movb $0, %dh ; \ addl $0xcfc, %edx ; \ outb %al, %dx /* * Macro: PCI_WRITE_CONFIG_WORD * Arguments: %eax address to write to (includes bus, device, function, &offset) * %ecx word to write * * Results: none * * Trashed: %eax, %edx * Preserved: %ecx * Effects: writes a single byte to pci config space * * Notes: This routine is optimized for minimal register usage. * * What it does is almost simple. * It preserves %eax (baring special bits) until it is written * out to the appropriate port. And hides the least significant * bits of the address in the high half of edx. * * In %edx[2] it stores the lower three bits of the address. */ #define PCI_WRITE_CONFIG_WORD \ movb %al, %dl ; \ andl $0x3, %edx ; \ shll $16, %edx ; \ \ orl $0x80000000, %eax ; \ andl $0xfffffffc, %eax ; \ movw $0xcf8, %dx ; \ outl %eax, %dx ; \ \ shrl $16, %edx ; \ movl %ecx, %eax ; \ addl $0xcfc, %edx ; \ outw %ax, %dx /* * Macro: PCI_WRITE_CONFIG_DWORD * Arguments: %eax address to write to (includes bus, device, function, &offset) * %ecx dword to write * * Results: none * * Trashed: %eax, %edx * Preserved: %ecx * Effects: writes a single byte to pci config space * * Notes: This routine is optimized for minimal register usage. * * What it does is almost simple. * It preserves %eax (baring special bits) until it is written * out to the appropriate port. And hides the least significant * bits of the address in the high half of edx. * * In %edx[2] it stores the lower three bits of the address. */ #define PCI_WRITE_CONFIG_DWORD \ movb %al, %dl ; \ andl $0x3, %edx ; \ shll $16, %edx ; \ \ orl $0x80000000, %eax ; \ andl $0xfffffffc, %eax ; \ movw $0xcf8, %dx ; \ outl %eax, %dx ; \ \ shrl $16, %edx ; \ movl %ecx, %eax ; \ addl $0xcfc, %edx ; \ outl %eax, %dx /* * Macro: PCI_READ_CONFIG_BYTE * Arguments: %eax address to read from (includes bus, device, function, &offset) * * Results: %al Byte read * * Trashed: %eax, %edx * Effects: reads a single byte from pci config space * * Notes: This routine is optimized for minimal register usage. * * What it does is almost simple. * It preserves %eax (baring special bits) until it is written * out to the appropriate port. And hides the least significant * bits of the address in the high half of edx. * * In %edx[2] it stores the lower three bits of the address. */ #define PCI_READ_CONFIG_BYTE \ movb %al, %dl ; \ andl $0x3, %edx ; \ shll $16, %edx ; \ \ orl $0x80000000, %eax ; \ andl $0xfffffffc, %eax ; \ movw $0xcf8, %dx ; \ outl %eax, %dx ; \ \ shrl $16, %edx ; \ addl $0xcfc, %edx ; \ inb %dx, %al /* * Macro: PCI_READ_CONFIG_WORD * Arguments: %eax address to read from (includes bus, device, function, &offset) * * Results: %ax word read * * Trashed: %eax, %edx * Effects: reads a 2 bytes from pci config space * * Notes: This routine is optimized for minimal register usage. * * What it does is almost simple. * It preserves %eax (baring special bits) until it is written * out to the appropriate port. And hides the least significant * bits of the address in the high half of edx. * * In %edx[2] it stores the lower three bits of the address. */ #define PCI_READ_CONFIG_WORD \ movb %al, %dl ; \ andl $0x3, %edx ; \ shll $16, %edx ; \ \ orl $0x80000000, %eax ; \ andl $0xfffffffc, %eax ; \ movw $0xcf8, %dx ; \ outl %eax, %dx ; \ \ shrl $16, %edx ; \ addl $0xcfc, %edx ; \ inw %dx, %ax /* * Macro: PCI_READ_CONFIG_DWORD * Arguments: %eax address to read from (includes bus, device, function, &offset) * * Results: %eax * * Trashed: %edx * Effects: reads 4 bytes from pci config space * * Notes: This routine is optimized for minimal register usage. * * What it does is almost simple. * It preserves %eax (baring special bits) until it is written * out to the appropriate port. And hides the least significant * bits of the address in the high half of edx. * * In %edx[2] it stores the lower three bits of the address. */ #define PCI_READ_CONFIG_DWORD \ movb %al, %dl ; \ andl $0x3, %edx ; \ shll $16, %edx ; \ \ orl $0x80000000, %eax ; \ andl $0xfffffffc, %eax ; \ movw $0xcf8, %dx ; \ outl %eax, %dx ; \ \ shrl $16, %edx ; \ addl $0xcfc, %edx ; \ inl %dx, %eax