176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * core/fs/pxe/isr.c 376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Stub invoked on return from real mode including from an interrupt. 576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Interrupts are locked out on entry. 676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "core.h" 976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "thread.h" 1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "pxe.h" 1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <string.h> 1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <sys/cpu.h> 1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <sys/io.h> 1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanextern uint8_t pxe_irq_pending; 1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanextern volatile uint8_t pxe_need_poll; 1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic DECLARE_INIT_SEMAPHORE(pxe_receive_thread_sem, 0); 1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic DECLARE_INIT_SEMAPHORE(pxe_poll_thread_sem, 0); 1976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic struct thread *pxe_thread, *poll_thread; 2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifndef PXE_POLL_FORCE 2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman# define PXE_POLL_FORCE 0 2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif 2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifndef PXE_POLL_BY_MODEL 2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman# define PXE_POLL_BY_MODEL 1 2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif 2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Note: this *must* be called with interrupts enabled. 3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic bool install_irq_vector(uint8_t irq, void (*isr)(void), far_ptr_t *old) 3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman far_ptr_t *entry; 3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned int vec; 3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint8_t mask, mymask; 3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint32_t now; 3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman bool ok; 3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (irq < 8) 4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman vec = irq + 0x08; 4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else if (irq < 16) 4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman vec = (irq - 8) + 0x70; 4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else 4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return false; 4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cli(); 4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (pxe_need_poll) { 5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sti(); 5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return false; 5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman entry = (far_ptr_t *)(vec << 2); 5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *old = *entry; 5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman entry->ptr = (uint32_t)isr; 5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Enable this interrupt at the PIC level, just in case... */ 5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mymask = ~(1 << (irq & 7)); 6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (irq >= 8) { 6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mask = inb(0x21); 6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mask &= ~(1 << 2); /* Enable cascade */ 6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outb(mask, 0x21); 6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mask = inb(0xa1); 6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mask &= mymask; 6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outb(mask, 0xa1); 6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mask = inb(0x21); 6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mask &= mymask; 7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman outb(mask, 0x21); 7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sti(); 7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman now = jiffies(); 7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Some time to watch for stuck interrupts */ 7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (jiffies() - now < 4 && (ok = !pxe_need_poll)) 7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman hlt(); 8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!ok) 8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *entry = *old; /* Restore the old vector */ 8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ddprintf("UNDI: IRQ %d(0x%02x): %04x:%04x -> %04x:%04x\n", irq, vec, 8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman old->seg, old->offs, entry->seg, entry->offs); 8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return ok; 8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic bool uninstall_irq_vector(uint8_t irq, void (*isr), far_ptr_t *old) 9176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 9276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman far_ptr_t *entry; 9376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned int vec; 9476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman bool rv; 9576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 9676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!irq) 9776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return true; /* Nothing to uninstall */ 9876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 9976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (irq < 8) 10076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman vec = irq + 0x08; 10176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else if (irq < 16) 10276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman vec = (irq - 8) + 0x70; 10376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else 10476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return false; 10576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 10676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cli(); 10776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 10876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman entry = (far_ptr_t *)(vec << 2); 10976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 11076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (entry->ptr != (uint32_t)isr) { 11176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rv = false; 11276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 11376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *entry = *old; 11476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman rv = true; 11576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 11676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 11776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sti(); 11876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return rv; 11976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 12076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 12176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void pxe_poll_wakeups(void) 12276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 12376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman static jiffies_t last_jiffies = 0; 12476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman jiffies_t now = jiffies(); 12576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 12676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (pxe_need_poll == 1) { 12776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* If we need polling now, activate polling */ 12876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman pxe_need_poll = 3; 12976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sem_up(&pxe_poll_thread_sem); 13076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 13176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 13276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (now != last_jiffies) { 13376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman last_jiffies = now; 13476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman __thread_process_timeouts(); 13576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 13676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 13776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (pxe_irq_pending) { 13876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman pxe_irq_pending = 0; 13976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sem_up(&pxe_receive_thread_sem); 14076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 14176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 14276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 14376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void pxe_process_irq(void) 14476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 14576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman static __lowmem t_PXENV_UNDI_ISR isr; 14676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 14776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint16_t func = PXENV_UNDI_ISR_IN_PROCESS; /* First time */ 14876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman bool done = false; 14976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 15076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (!done) { 15176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memset(&isr, 0, sizeof isr); 15276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman isr.FuncFlag = func; 15376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman func = PXENV_UNDI_ISR_IN_GET_NEXT; /* Next time */ 15476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 15576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman pxe_call(PXENV_UNDI_ISR, &isr); 15676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 15776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman switch (isr.FuncFlag) { 15876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case PXENV_UNDI_ISR_OUT_DONE: 15976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman done = true; 16076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 16176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 16276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case PXENV_UNDI_ISR_OUT_TRANSMIT: 16376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Transmit complete - nothing for us to do */ 16476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 16576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 16676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case PXENV_UNDI_ISR_OUT_RECEIVE: 16776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman undiif_input(&isr); 16876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 16976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 17076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case PXENV_UNDI_ISR_OUT_BUSY: 17176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* ISR busy, this should not happen */ 17276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman done = true; 17376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 17476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 17576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman default: 17676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Invalid return code, this should not happen */ 17776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman done = true; 17876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 17976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 18076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 18176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 18276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 18376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void pxe_receive_thread(void *dummy) 18476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 18576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (void)dummy; 18676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 18776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (;;) { 18876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sem_down(&pxe_receive_thread_sem, 0); 18976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman pxe_process_irq(); 19076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 19176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 19276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 19376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic bool pxe_isr_poll(void) 19476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 19576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman static __lowmem t_PXENV_UNDI_ISR isr; 19676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 19776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman isr.FuncFlag = PXENV_UNDI_ISR_IN_START; 19876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman pxe_call(PXENV_UNDI_ISR, &isr); 19976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 20076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return isr.FuncFlag == PXENV_UNDI_ISR_OUT_OURS; 20176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 20276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 20376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void pxe_poll_thread(void *dummy) 20476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 20576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (void)dummy; 20676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 20776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Block indefinitely unless activated */ 20876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sem_down(&pxe_poll_thread_sem, 0); 20976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 21076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (;;) { 21176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cli(); 21276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (pxe_receive_thread_sem.count < 0 && pxe_isr_poll()) 21376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sem_up(&pxe_receive_thread_sem); 21476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else 21576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman __schedule(); 21676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sti(); 21776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cpu_relax(); 21876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 21976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 22076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 22176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 22276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * This does preparations and enables the PXE thread 22376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 22476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid pxe_init_isr(void) 22576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 22676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman start_idle_thread(); 22776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sched_hook_func = pxe_poll_wakeups; 22876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 22976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Run the pxe receive thread at elevated priority, since the UNDI 23076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * stack is likely to have very limited memory available; therefore to 23176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * avoid packet loss we need to move it into memory that we ourselves 23276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * manage, as soon as possible. 23376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 23476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman core_pm_hook = __schedule; 23576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 23676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman pxe_thread = start_thread("pxe receive", 16384, -20, 23776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman pxe_receive_thread, NULL); 23876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 23976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 24076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 24176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Actually start the interrupt routine inside the UNDI stack 24276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 24376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid pxe_start_isr(void) 24476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 24576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int irq = pxe_undi_info.IntNumber; 24676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 24776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (irq == 2) 24876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman irq = 9; /* IRQ 2 is really IRQ 9 */ 24976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman else if (irq > 15) 25076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman irq = 0; /* Invalid IRQ */ 25176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 25276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman pxe_irq_vector = irq; 25376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 25476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (irq) { 25576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!install_irq_vector(irq, pxe_isr, &pxe_irq_chain)) 25676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman irq = 0; /* Install failed or stuck interrupt */ 25776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 25876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 25976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman poll_thread = start_thread("pxe poll", 4096, POLL_THREAD_PRIORITY, 26076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman pxe_poll_thread, NULL); 26176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 26276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!irq || !(pxe_undi_iface.ServiceFlags & PXE_UNDI_IFACE_FLAG_IRQ)) { 26376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman asm volatile("orb $1,%0" : "+m" (pxe_need_poll)); 26476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman dprintf("pxe_start_isr: forcing pxe_need_poll\n"); 26576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else if (PXE_POLL_BY_MODEL) { 26676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman dprintf("pxe_start_isr: trying poll by model\n"); 26776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int hwad = ((int)MAC[0] << 16) + ((int)MAC[1] << 8) + MAC[2]; 26876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman dprintf("pxe_start_isr: got %06x %04x\n", hwad, pxe_undi_iface.ServiceFlags); 26976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ((hwad == 0x000023ae) && (pxe_undi_iface.ServiceFlags == 0xdc1b) || 27076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (hwad == 0x005c260a) && (pxe_undi_iface.ServiceFlags == 0xdc1b) || 27176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (hwad == 0x00180373) && (pxe_undi_iface.ServiceFlags == 0xdc1b)) { 27276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman asm volatile("orb $1,%0" : "+m" (pxe_need_poll)); 27376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman dprintf("pxe_start_isr: forcing pxe_need_poll by model\n"); 27476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 27576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 27676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 27776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 27876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint reset_pxe(void) 27976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 28076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman static __lowmem struct s_PXENV_UNDI_CLOSE undi_close; 28176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 28276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sched_hook_func = NULL; 28376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman core_pm_hook = core_pm_null_hook; 28476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman kill_thread(pxe_thread); 28576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 28676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memset(&undi_close, 0, sizeof(undi_close)); 28776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman pxe_call(PXENV_UNDI_CLOSE, &undi_close); 28876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 28976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (undi_close.Status) 29076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("PXENV_UNDI_CLOSE failed: 0x%x\n", undi_close.Status); 29176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 29276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (pxe_irq_vector) 29376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uninstall_irq_vector(pxe_irq_vector, pxe_isr, &pxe_irq_chain); 29476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (poll_thread) 29576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman kill_thread(poll_thread); 29676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 29776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return undi_close.Status; 29876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 299