mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
Fix drivers not detecting PCI devices without an interrupt line.
This commit is contained in:
parent
da89dec2e2
commit
2b6463aa95
6 changed files with 44 additions and 13 deletions
|
@ -126,6 +126,13 @@ void HBA__OnInterrupt(struct interrupt_context*, void* context)
|
||||||
|
|
||||||
bool HBA::Initialize(Ref<Descriptor> dev, const char* devpath)
|
bool HBA::Initialize(Ref<Descriptor> dev, const char* devpath)
|
||||||
{
|
{
|
||||||
|
interrupt_index = PCI::SetupInterruptLine(devaddr);
|
||||||
|
if ( !interrupt_index )
|
||||||
|
{
|
||||||
|
LogF("error: cannot determine interrupt line");
|
||||||
|
return errno = EINVAL, false;
|
||||||
|
}
|
||||||
|
|
||||||
pcibar_t mmio_bar = PCI::GetBAR(devaddr, 5);
|
pcibar_t mmio_bar = PCI::GetBAR(devaddr, 5);
|
||||||
if ( mmio_bar.size() < sizeof(struct hba_regs) && /* or || ? */
|
if ( mmio_bar.size() < sizeof(struct hba_regs) && /* or || ? */
|
||||||
mmio_bar.size() < 1024 )
|
mmio_bar.size() < 1024 )
|
||||||
|
@ -228,8 +235,6 @@ bool HBA::Initialize(Ref<Descriptor> dev, const char* devpath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interrupt_index =
|
|
||||||
Interrupt::IRQ0 + PCI::Read8(devaddr, PCIFIELD_INTERRUPT_LINE);
|
|
||||||
interrupt_registration.handler = HBA__OnInterrupt;
|
interrupt_registration.handler = HBA__OnInterrupt;
|
||||||
interrupt_registration.context = this;
|
interrupt_registration.context = this;
|
||||||
Interrupt::RegisterHandler(interrupt_index, &interrupt_registration);
|
Interrupt::RegisterHandler(interrupt_index, &interrupt_registration);
|
||||||
|
|
|
@ -56,7 +56,7 @@ private:
|
||||||
addralloc_t mmio_alloc;
|
addralloc_t mmio_alloc;
|
||||||
volatile struct hba_regs* regs;
|
volatile struct hba_regs* regs;
|
||||||
uint32_t devaddr;
|
uint32_t devaddr;
|
||||||
unsigned int interrupt_index;
|
uint8_t interrupt_index;
|
||||||
bool interrupt_registered;
|
bool interrupt_registered;
|
||||||
bool mmio_alloced;
|
bool mmio_alloced;
|
||||||
|
|
||||||
|
|
|
@ -147,7 +147,7 @@ void FixDefaultDeviceBars(pcibar_t* basebar, pcibar_t* ctrlbar, uint8_t* irq,
|
||||||
bool compatibility = interface == 0x00 || interface == 0x02;
|
bool compatibility = interface == 0x00 || interface == 0x02;
|
||||||
|
|
||||||
if ( compatibility )
|
if ( compatibility )
|
||||||
*irq = channel_index == 0 ? 14 : 15;
|
*irq = channel_index == 0 ? Interrupt::IRQ14 : Interrupt::IRQ15;
|
||||||
|
|
||||||
if ( compatibility ||
|
if ( compatibility ||
|
||||||
basebar->addr_raw == 0 ||
|
basebar->addr_raw == 0 ||
|
||||||
|
@ -175,8 +175,14 @@ bool Channel::Initialize(Ref<Descriptor> dev, const char* devpath)
|
||||||
pcibar_t basebar = PCI::GetBAR(devaddr, 2 * channel_index + 0);
|
pcibar_t basebar = PCI::GetBAR(devaddr, 2 * channel_index + 0);
|
||||||
pcibar_t ctrlbar = PCI::GetBAR(devaddr, 2 * channel_index + 1);
|
pcibar_t ctrlbar = PCI::GetBAR(devaddr, 2 * channel_index + 1);
|
||||||
pcibar_t busmasterbar = PCI::GetBAR(devaddr, 4);
|
pcibar_t busmasterbar = PCI::GetBAR(devaddr, 4);
|
||||||
uint8_t irq = PCI::Read8(devaddr, PCIFIELD_INTERRUPT_LINE);
|
interrupt_index = PCI::SetupInterruptLine(devaddr);
|
||||||
FixDefaultDeviceBars(&basebar, &ctrlbar, &irq, channel_index, interface);
|
FixDefaultDeviceBars(&basebar, &ctrlbar, &interrupt_index, channel_index, interface);
|
||||||
|
|
||||||
|
if ( !interrupt_index )
|
||||||
|
{
|
||||||
|
LogF("error: cannot determine interrupt line");
|
||||||
|
return errno = EINVAL, false;
|
||||||
|
}
|
||||||
|
|
||||||
if ( !basebar.is_iospace() )
|
if ( !basebar.is_iospace() )
|
||||||
{
|
{
|
||||||
|
@ -255,8 +261,6 @@ bool Channel::Initialize(Ref<Descriptor> dev, const char* devpath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interrupt_index = Interrupt::IRQ0 + irq;
|
|
||||||
|
|
||||||
interrupt_registration.handler = Channel__OnInterrupt;
|
interrupt_registration.handler = Channel__OnInterrupt;
|
||||||
interrupt_registration.context = this;
|
interrupt_registration.context = this;
|
||||||
Interrupt::RegisterHandler(interrupt_index, &interrupt_registration);
|
Interrupt::RegisterHandler(interrupt_index, &interrupt_registration);
|
||||||
|
|
|
@ -61,7 +61,7 @@ private:
|
||||||
uint16_t port_control;
|
uint16_t port_control;
|
||||||
uint16_t busmaster_base;
|
uint16_t busmaster_base;
|
||||||
Port* drives[2];
|
Port* drives[2];
|
||||||
unsigned int interrupt_index;
|
uint8_t interrupt_index;
|
||||||
bool interrupt_registered;
|
bool interrupt_registered;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011, 2012, 2013, 2014, 2015 Jonas 'Sortie' Termansen.
|
* Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016 Jonas 'Sortie' Termansen.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -152,6 +152,7 @@ pcibar_t GetExpansionROM(uint32_t devaddr);
|
||||||
void EnableExpansionROM(uint32_t devaddr);
|
void EnableExpansionROM(uint32_t devaddr);
|
||||||
void DisableExpansionROM(uint32_t devaddr);
|
void DisableExpansionROM(uint32_t devaddr);
|
||||||
bool IsExpansionROMEnabled(uint32_t devaddr);
|
bool IsExpansionROMEnabled(uint32_t devaddr);
|
||||||
|
uint8_t SetupInterruptLine(uint32_t devaddr);
|
||||||
|
|
||||||
} // namespace PCI
|
} // namespace PCI
|
||||||
} // namespace Sortix
|
} // namespace Sortix
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011, 2012, 2013, 2014 Jonas 'Sortie' Termansen.
|
* Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016 Jonas 'Sortie' Termansen.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -21,6 +21,7 @@
|
||||||
#include <endian.h>
|
#include <endian.h>
|
||||||
|
|
||||||
#include <sortix/kernel/cpu.h>
|
#include <sortix/kernel/cpu.h>
|
||||||
|
#include <sortix/kernel/interrupt.h>
|
||||||
#include <sortix/kernel/ioport.h>
|
#include <sortix/kernel/ioport.h>
|
||||||
#include <sortix/kernel/kernel.h>
|
#include <sortix/kernel/kernel.h>
|
||||||
#include <sortix/kernel/kthread.h>
|
#include <sortix/kernel/kthread.h>
|
||||||
|
@ -31,8 +32,8 @@ namespace PCI {
|
||||||
|
|
||||||
static kthread_mutex_t pci_lock = KTHREAD_MUTEX_INITIALIZER;
|
static kthread_mutex_t pci_lock = KTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
const uint16_t CONFIG_ADDRESS = 0xCF8;
|
static const uint16_t CONFIG_ADDRESS = 0xCF8;
|
||||||
const uint16_t CONFIG_DATA = 0xCFC;
|
static const uint16_t CONFIG_DATA = 0xCFC;
|
||||||
|
|
||||||
uint32_t MakeDevAddr(uint8_t bus, uint8_t slot, uint8_t func)
|
uint32_t MakeDevAddr(uint8_t bus, uint8_t slot, uint8_t func)
|
||||||
{
|
{
|
||||||
|
@ -279,6 +280,26 @@ bool IsExpansionROMEnabled(uint32_t devaddr)
|
||||||
return PCI::Read32(devaddr, 0x30) & 0x1;
|
return PCI::Read32(devaddr, 0x30) & 0x1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool IsOkayInterruptLine(uint8_t line)
|
||||||
|
{
|
||||||
|
if ( line == 0 )
|
||||||
|
return false; // Conflict with PIT.
|
||||||
|
if ( line == 2 )
|
||||||
|
return false; // Cascade, can't be received.
|
||||||
|
if ( 16 <= line )
|
||||||
|
return false; // Not in set of valid IRQs.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t SetupInterruptLine(uint32_t devaddr)
|
||||||
|
{
|
||||||
|
ScopedLock lock(&pci_lock);
|
||||||
|
uint8_t line = Read8(devaddr, PCIFIELD_INTERRUPT_LINE);
|
||||||
|
if ( !IsOkayInterruptLine(line) )
|
||||||
|
return 0;
|
||||||
|
return Interrupt::IRQ0 + line;
|
||||||
|
}
|
||||||
|
|
||||||
void Init()
|
void Init()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue