📄 firmware.c
字号:
spin_lock_irq(&pdc_lock); retval = mem_pdc_call(PDC_SOFT_POWER, PDC_SOFT_POWER_INFO, __pa(pdc_result), 0); if (retval == PDC_OK) { convert_to_wide(pdc_result); *power_reg = f_extend(pdc_result[0]); } spin_unlock_irq(&pdc_lock); return retval;}/* * pdc_soft_power_button - Control the soft power button behaviour * @sw_control: 0 for hardware control, 1 for software control * * * This PDC function places the soft power button under software or * hardware control. * Under software control the OS may control to when to allow to shut * down the system. Under hardware control pressing the power button * powers off the system immediately. */int pdc_soft_power_button(int sw_control){ int retval; spin_lock_irq(&pdc_lock); retval = mem_pdc_call(PDC_SOFT_POWER, PDC_SOFT_POWER_ENABLE, __pa(pdc_result), sw_control); spin_unlock_irq(&pdc_lock); return retval;}/* * pdc_io_reset - Hack to avoid overlapping range registers of Bridges devices. * Primarily a problem on T600 (which parisc-linux doesn't support) but * who knows what other platform firmware might do with this OS "hook". */void pdc_io_reset(void){ spin_lock_irq(&pdc_lock); mem_pdc_call(PDC_IO, PDC_IO_RESET, 0); spin_unlock_irq(&pdc_lock);}/* * pdc_io_reset_devices - Hack to Stop USB controller * * If PDC used the usb controller, the usb controller * is still running and will crash the machines during iommu * setup, because of still running DMA. This PDC call * stops the USB controller. * Normally called after calling pdc_io_reset(). */void pdc_io_reset_devices(void){ spin_lock_irq(&pdc_lock); mem_pdc_call(PDC_IO, PDC_IO_RESET_DEVICES, 0); spin_unlock_irq(&pdc_lock);}/** * pdc_iodc_putc - Console character print using IODC. * @c: the character to output. * * Note that only these special chars are architected for console IODC io: * BEL, BS, CR, and LF. Others are passed through. * Since the HP console requires CR+LF to perform a 'newline', we translate * "\n" to "\r\n". */void pdc_iodc_putc(unsigned char c){ /* XXX Should we spinlock posx usage */ static int posx; /* for simple TAB-Simulation... */ static int __attribute__((aligned(8))) iodc_retbuf[32]; static char __attribute__((aligned(64))) iodc_dbuf[4096]; unsigned int n; unsigned int flags; switch (c) { case '\n': iodc_dbuf[0] = '\r'; iodc_dbuf[1] = '\n'; n = 2; posx = 0; break; case '\t': pdc_iodc_putc(' '); while (posx & 7) /* expand TAB */ pdc_iodc_putc(' '); return; /* return since IODC can't handle this */ case '\b': posx-=2; /* BS */ default: iodc_dbuf[0] = c; n = 1; posx++; break; } spin_lock_irqsave(&pdc_lock, flags); real32_call(PAGE0->mem_cons.iodc_io, (unsigned long)PAGE0->mem_cons.hpa, ENTRY_IO_COUT, PAGE0->mem_cons.spa, __pa(PAGE0->mem_cons.dp.layers), __pa(iodc_retbuf), 0, __pa(iodc_dbuf), n, 0); spin_unlock_irqrestore(&pdc_lock, flags);}/** * pdc_iodc_outc - Console character print using IODC (without conversions). * @c: the character to output. * * Write the character directly to the IODC console. */void pdc_iodc_outc(unsigned char c){ unsigned int n, flags; /* fill buffer with one caracter and print it */ static int __attribute__((aligned(8))) iodc_retbuf[32]; static char __attribute__((aligned(64))) iodc_dbuf[4096]; n = 1; iodc_dbuf[0] = c; spin_lock_irqsave(&pdc_lock, flags); real32_call(PAGE0->mem_cons.iodc_io, (unsigned long)PAGE0->mem_cons.hpa, ENTRY_IO_COUT, PAGE0->mem_cons.spa, __pa(PAGE0->mem_cons.dp.layers), __pa(iodc_retbuf), 0, __pa(iodc_dbuf), n, 0); spin_unlock_irqrestore(&pdc_lock, flags);}/** * pdc_iodc_getc - Read a character (non-blocking) from the PDC console. * * Read a character (non-blocking) from the PDC console, returns -1 if * key is not present. */int pdc_iodc_getc(void){ unsigned int flags; static int __attribute__((aligned(8))) iodc_retbuf[32]; static char __attribute__((aligned(64))) iodc_dbuf[4096]; int ch; int status; /* Bail if no console input device. */ if (!PAGE0->mem_kbd.iodc_io) return 0; /* wait for a keyboard (rs232)-input */ spin_lock_irqsave(&pdc_lock, flags); real32_call(PAGE0->mem_kbd.iodc_io, (unsigned long)PAGE0->mem_kbd.hpa, ENTRY_IO_CIN, PAGE0->mem_kbd.spa, __pa(PAGE0->mem_kbd.dp.layers), __pa(iodc_retbuf), 0, __pa(iodc_dbuf), 1, 0); ch = *iodc_dbuf; status = *iodc_retbuf; spin_unlock_irqrestore(&pdc_lock, flags); if (status == 0) return -1; return ch;}int pdc_sti_call(unsigned long func, unsigned long flags, unsigned long inptr, unsigned long outputr, unsigned long glob_cfg){ int retval; spin_lock_irq(&pdc_lock); retval = real32_call(func, flags, inptr, outputr, glob_cfg); spin_unlock_irq(&pdc_lock); return retval;}EXPORT_SYMBOL(pdc_sti_call);#ifdef __LP64__/** * pdc_pat_cell_get_number - Returns the cell number. * @cell_info: The return buffer. * * This PDC call returns the cell number of the cell from which the call * is made. */int pdc_pat_cell_get_number(struct pdc_pat_cell_num *cell_info){ int retval; spin_lock_irq(&pdc_lock); retval = mem_pdc_call(PDC_PAT_CELL, PDC_PAT_CELL_GET_NUMBER, __pa(pdc_result)); memcpy(cell_info, pdc_result, sizeof(*cell_info)); spin_unlock_irq(&pdc_lock); return retval;}/** * pdc_pat_cell_module - Retrieve the cell's module information. * @actcnt: The number of bytes written to mem_addr. * @ploc: The physical location. * @mod: The module index. * @view_type: The view of the address type. * @mem_addr: The return buffer. * * This PDC call returns information about each module attached to the cell * at the specified location. */int pdc_pat_cell_module(unsigned long *actcnt, unsigned long ploc, unsigned long mod, unsigned long view_type, void *mem_addr){ int retval; static struct pdc_pat_cell_mod_maddr_block result __attribute__ ((aligned (8))); spin_lock_irq(&pdc_lock); retval = mem_pdc_call(PDC_PAT_CELL, PDC_PAT_CELL_MODULE, __pa(pdc_result), ploc, mod, view_type, __pa(&result)); if(!retval) { *actcnt = pdc_result[0]; memcpy(mem_addr, &result, *actcnt); } spin_unlock_irq(&pdc_lock); return retval;}/** * pdc_pat_cpu_get_number - Retrieve the cpu number. * @cpu_info: The return buffer. * @hpa: The Hard Physical Address of the CPU. * * Retrieve the cpu number for the cpu at the specified HPA. */int pdc_pat_cpu_get_number(struct pdc_pat_cpu_num *cpu_info, void *hpa){ int retval; spin_lock_irq(&pdc_lock); retval = mem_pdc_call(PDC_PAT_CPU, PDC_PAT_CPU_GET_NUMBER, __pa(&pdc_result), hpa); memcpy(cpu_info, pdc_result, sizeof(*cpu_info)); spin_unlock_irq(&pdc_lock); return retval;}/** * pdc_pat_get_irt_size - Retrieve the number of entries in the cell's interrupt table. * @num_entries: The return value. * @cell_num: The target cell. * * This PDC function returns the number of entries in the specified cell's * interrupt table. */int pdc_pat_get_irt_size(unsigned long *num_entries, unsigned long cell_num){ int retval; spin_lock_irq(&pdc_lock); retval = mem_pdc_call(PDC_PAT_IO, PDC_PAT_IO_GET_PCI_ROUTING_TABLE_SIZE, __pa(pdc_result), cell_num); *num_entries = pdc_result[0]; spin_unlock_irq(&pdc_lock); return retval;}/** * pdc_pat_get_irt - Retrieve the cell's interrupt table. * @r_addr: The return buffer. * @cell_num: The target cell. * * This PDC function returns the actual interrupt table for the specified cell. */int pdc_pat_get_irt(void *r_addr, unsigned long cell_num){ int retval; spin_lock_irq(&pdc_lock); retval = mem_pdc_call(PDC_PAT_IO, PDC_PAT_IO_GET_PCI_ROUTING_TABLE, __pa(r_addr), cell_num); spin_unlock_irq(&pdc_lock); return retval;}/** * pdc_pat_pd_get_addr_map - Retrieve information about memory address ranges. * @actlen: The return buffer. * @mem_addr: Pointer to the memory buffer. * @count: The number of bytes to read from the buffer. * @offset: The offset with respect to the beginning of the buffer. * */int pdc_pat_pd_get_addr_map(unsigned long *actual_len, void *mem_addr, unsigned long count, unsigned long offset){ int retval; spin_lock_irq(&pdc_lock); retval = mem_pdc_call(PDC_PAT_PD, PDC_PAT_PD_GET_ADDR_MAP, __pa(pdc_result), __pa(pdc_result2), count, offset); *actual_len = pdc_result[0]; memcpy(mem_addr, pdc_result2, *actual_len); spin_unlock_irq(&pdc_lock); return retval;}/** * pdc_pat_io_pci_cfg_read - Read PCI configuration space. * @pci_addr: PCI configuration space address for which the read request is being made. * @pci_size: Size of read in bytes. Valid values are 1, 2, and 4. * @mem_addr: Pointer to return memory buffer. * */int pdc_pat_io_pci_cfg_read(unsigned long pci_addr, int pci_size, u32 *mem_addr){ int retval; spin_lock_irq(&pdc_lock); retval = mem_pdc_call(PDC_PAT_IO, PDC_PAT_IO_PCI_CONFIG_READ, __pa(pdc_result), pci_addr, pci_size); switch(pci_size) { case 1: *(u8 *) mem_addr = (u8) pdc_result[0]; case 2: *(u16 *)mem_addr = (u16) pdc_result[0]; case 4: *(u32 *)mem_addr = (u32) pdc_result[0]; } spin_unlock_irq(&pdc_lock); return retval;}/** * pdc_pat_io_pci_cfg_write - Retrieve information about memory address ranges. * @pci_addr: PCI configuration space address for which the write request is being made. * @pci_size: Size of write in bytes. Valid values are 1, 2, and 4. * @value: Pointer to 1, 2, or 4 byte value in low order end of argument to be * written to PCI Config space. * */int pdc_pat_io_pci_cfg_write(unsigned long pci_addr, int pci_size, u32 val){ int retval; spin_lock_irq(&pdc_lock); retval = mem_pdc_call(PDC_PAT_IO, PDC_PAT_IO_PCI_CONFIG_WRITE, pci_addr, pci_size, val); spin_unlock_irq(&pdc_lock); return retval;}#endif /* __LP64__ *//***************** 32-bit real-mode calls ***********//* The struct below is used * to overlay real_stack (real2.S), preparing a 32-bit call frame. * real32_call_asm() then uses this stack in narrow real mode */struct narrow_stack { /* use int, not long which is 64 bits */ unsigned int arg13; unsigned int arg12; unsigned int arg11; unsigned int arg10; unsigned int arg9; unsigned int arg8; unsigned int arg7; unsigned int arg6; unsigned int arg5; unsigned int arg4; unsigned int arg3; unsigned int arg2; unsigned int arg1; unsigned int arg0; unsigned int frame_marker[8]; unsigned int sp; /* in reality, there's nearly 8k of stack after this */};long real32_call(unsigned long fn, ...){ va_list args; extern struct narrow_stack real_stack; extern unsigned long real32_call_asm(unsigned int *, unsigned int *, unsigned int); va_start(args, fn); real_stack.arg0 = va_arg(args, unsigned int); real_stack.arg1 = va_arg(args, unsigned int); real_stack.arg2 = va_arg(args, unsigned int); real_stack.arg3 = va_arg(args, unsigned int); real_stack.arg4 = va_arg(args, unsigned int); real_stack.arg5 = va_arg(args, unsigned int); real_stack.arg6 = va_arg(args, unsigned int); real_stack.arg7 = va_arg(args, unsigned int); real_stack.arg8 = va_arg(args, unsigned int); real_stack.arg9 = va_arg(args, unsigned int); real_stack.arg10 = va_arg(args, unsigned int); real_stack.arg11 = va_arg(args, unsigned int); real_stack.arg12 = va_arg(args, unsigned int); real_stack.arg13 = va_arg(args, unsigned int); va_end(args); return real32_call_asm(&real_stack.sp, &real_stack.arg0, fn);}#ifdef __LP64__/***************** 64-bit real-mode calls ***********/struct wide_stack { unsigned long arg0; unsigned long arg1; unsigned long arg2; unsigned long arg3; unsigned long arg4; unsigned long arg5; unsigned long arg6; unsigned long arg7; unsigned long arg8; unsigned long arg9; unsigned long arg10; unsigned long arg11; unsigned long arg12; unsigned long arg13; unsigned long frame_marker[2]; /* rp, previous sp */ unsigned long sp; /* in reality, there's nearly 8k of stack after this */};long real64_call(unsigned long fn, ...){ va_list args; extern struct wide_stack real64_stack; extern unsigned long real64_call_asm(unsigned long *, unsigned long *, unsigned long); va_start(args, fn); real64_stack.arg0 = va_arg(args, unsigned long); real64_stack.arg1 = va_arg(args, unsigned long); real64_stack.arg2 = va_arg(args, unsigned long); real64_stack.arg3 = va_arg(args, unsigned long); real64_stack.arg4 = va_arg(args, unsigned long); real64_stack.arg5 = va_arg(args, unsigned long); real64_stack.arg6 = va_arg(args, unsigned long); real64_stack.arg7 = va_arg(args, unsigned long); real64_stack.arg8 = va_arg(args, unsigned long); real64_stack.arg9 = va_arg(args, unsigned long); real64_stack.arg10 = va_arg(args, unsigned long); real64_stack.arg11 = va_arg(args, unsigned long); real64_stack.arg12 = va_arg(args, unsigned long); real64_stack.arg13 = va_arg(args, unsigned long); va_end(args); return real64_call_asm(&real64_stack.sp, &real64_stack.arg0, fn);}#endif /* __LP64__ */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -