/* Non blocking put character to console device, returns -1 if * unsuccessful. */ int prom_nbputchar(char c) { static char outc; unsigned long flags; int i = -1; spin_lock_irqsave(&prom_lock, flags); switch(prom_vers) { case PROM_V0: case PROM_SUN4: i = (*(romvec->pv_nbputchar))(c); break; case PROM_V2: case PROM_V3: outc = c; if( (*(romvec->pv_v2devops).v2_dev_write)(*romvec->pv_v2bootargs.fd_stdout, &outc, 0x1) == 1) i = 0; else i = -1; break; default: i = -1; break; }; restore_current(); spin_unlock_irqrestore(&prom_lock, flags); return i; /* Ugh, we could spin forever on unsupported proms ;( */ }
/* Non blocking get character from console input device, returns -1 * if no input was taken. This can be used for polling. */ int prom_nbgetchar(void) { static char inc; int i = -1; unsigned long flags; spin_lock_irqsave(&prom_lock, flags); switch(prom_vers) { case PROM_V0: case PROM_SUN4: i = (*(romvec->pv_nbgetchar))(); break; case PROM_V2: case PROM_V3: if( (*(romvec->pv_v2devops).v2_dev_read)(*romvec->pv_v2bootargs.fd_stdin , &inc, 0x1) == 1) { i = inc; } else { i = -1; } break; default: i = -1; break; }; restore_current(); spin_unlock_irqrestore(&prom_lock, flags); return i; /* Ugh, we could spin forever on unsupported proms ;( */ }
enum prom_output_device prom_query_output_device(void) { unsigned long flags; int st_p; char propb[64]; char *p; int propl; switch(prom_vers) { case PROM_V0: case PROM_SUN4: switch(*romvec->pv_stdin) { case PROMDEV_SCREEN: return PROMDEV_OSCREEN; case PROMDEV_TTYA: return PROMDEV_OTTYA; case PROMDEV_TTYB: return PROMDEV_OTTYB; }; break; case PROM_V2: case PROM_V3: spin_lock_irqsave(&prom_lock, flags); st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdout); restore_current(); spin_unlock_irqrestore(&prom_lock, flags); propl = prom_getproperty(st_p, "device_type", propb, sizeof(propb)); if (propl >= 0 && propl == sizeof("display") && strncmp("display", propb, sizeof("display")) == 0) { return PROMDEV_OSCREEN; } if(prom_vers == PROM_V3) { if(propl >= 0 && strncmp("serial", propb, sizeof("serial")) != 0) return PROMDEV_O_UNK; prom_getproperty(prom_root_node, "stdout-path", propb, sizeof(propb)); if(strncmp(propb, con_name_jmc, CON_SIZE_JMC) == 0) return PROMDEV_OTTYA; p = propb; while(*p) p++; p -= 2; if(p[0]==':') { if(p[1] == 'a') return PROMDEV_OTTYA; else if(p[1] == 'b') return PROMDEV_OTTYB; } } else { switch(*romvec->pv_stdin) { case PROMDEV_TTYA: return PROMDEV_OTTYA; case PROMDEV_TTYB: return PROMDEV_OTTYB; }; } break; default: ; }; return PROMDEV_O_UNK; }
/* Set physical segment 'segment' at virtual address 'vaddr' in * context 'ctx'. */ void prom_putsegment(int ctx, unsigned long vaddr, int segment) { unsigned long flags; spin_lock_irqsave(&prom_lock, flags); (*(romvec->pv_setctxt))(ctx, (char *) vaddr, segment); restore_current(); spin_unlock_irqrestore(&prom_lock, flags); return; }
/* Reset and reboot the machine with the command 'bcommand'. */ void prom_reboot(char *bcommand) { unsigned long flags; spin_lock_irqsave(&prom_lock, flags); (*(romvec->pv_reboot))(bcommand); /* Never get here. */ restore_current(); spin_unlock_irqrestore(&prom_lock, flags); }
/* Set physical segment 'segment' at virtual address 'vaddr' in * context 'ctx'. */ void prom_putsegment(int ctx, unsigned long vaddr, int segment) { unsigned long flags; save_flags(flags); cli(); (*(romvec->pv_setctxt))(ctx, (char *) vaddr, segment); restore_current(); restore_flags(flags); return; }
void prom_cmdline(void) { unsigned long flags; spin_lock_irqsave(&prom_lock, flags); (*(romvec->pv_abort))(); restore_current(); spin_unlock_irqrestore(&prom_lock, flags); set_auxio(AUXIO_LED, 0); }
/* Unmap an IO/device area that was mapped using the above routine. */ void prom_unmapio(char *vaddr, unsigned int num_bytes) { unsigned long flags; if(num_bytes == 0x0) return; spin_lock_irqsave(&prom_lock, flags); (*(romvec->pv_v2devops.v2_dumb_munmap))(vaddr, num_bytes); restore_current(); spin_unlock_irqrestore(&prom_lock, flags); }
/* Interal version of nextprop that does not alter return values. */ char * __prom_nextprop(int node, char * oprop) { unsigned long flags; char *prop; save_and_cli(flags); prop = prom_nodeops->no_nextprop(node, oprop); restore_current(); restore_flags(flags); return prop; }
/* Internal version of prom_getsibling that does not alter return values. */ static phandle __prom_getsibling(phandle node) { unsigned long flags; phandle cnode; spin_lock_irqsave(&prom_lock, flags); cnode = prom_nodeops->no_nextnode(node); restore_current(); spin_unlock_irqrestore(&prom_lock, flags); return cnode; }
/* Interal version of nextprop that does not alter return values. */ static char *__prom_nextprop(phandle node, char * oprop) { unsigned long flags; char *prop; spin_lock_irqsave(&prom_lock, flags); prop = prom_nodeops->no_nextprop(node, oprop); restore_current(); spin_unlock_irqrestore(&prom_lock, flags); return prop; }
int prom_inst2pkg(int inst) { int node; unsigned long flags; spin_lock_irqsave(&prom_lock, flags); node = (*romvec->pv_v2devops.v2_inst2pkg)(inst); restore_current(); spin_unlock_irqrestore(&prom_lock, flags); if (node == -1) return 0; return node; }
/* Internal version of prom_getchild that does not alter return values. */ int __prom_getchild(int node) { unsigned long flags; int cnode; spin_lock_irqsave(&prom_lock, flags); cnode = prom_nodeops->no_child(node); restore_current(); spin_unlock_irqrestore(&prom_lock, flags); return cnode; }
void __noreturn prom_halt(void) { unsigned long flags; again: spin_lock_irqsave(&prom_lock, flags); (*(romvec->pv_halt))(); /* */ restore_current(); spin_unlock_irqrestore(&prom_lock, flags); goto again; /* */ }
/* Drop into the prom, but completely terminate the program. * No chance of continuing. */ void prom_halt(void) { unsigned long flags; again: spin_lock_irqsave(&prom_lock, flags); (*(romvec->pv_halt))(); /* Never get here. */ restore_current(); spin_unlock_irqrestore(&prom_lock, flags); goto again; /* PROM is out to get me -DaveM */ }
/* Internal version of prom_getsibling that does not alter return values. */ int __prom_getsibling(int node) { unsigned long flags; int cnode; save_and_cli(flags); cnode = prom_nodeops->no_nextnode(node); restore_current(); restore_flags(flags); return cnode; }
int prom_inst2pkg(int inst) { int node; unsigned long flags; save_flags(flags); cli(); node = (*romvec->pv_v2devops.v2_inst2pkg)(inst); restore_current(); restore_flags(flags); if (node == -1) return 0; return node; }
/* Set property 'pname' at node 'node' to value 'value' which has a length * of 'size' bytes. Return the number of bytes the prom accepted. */ int prom_setprop(int node, char *pname, char *value, int size) { unsigned long flags; int ret; if(size == 0) return 0; if((pname == 0) || (value == 0)) return 0; spin_lock_irqsave(&prom_lock, flags); ret = prom_nodeops->no_setprop(node, pname, value, size); restore_current(); spin_unlock_irqrestore(&prom_lock, flags); return ret; }
/* Menu-specific shortcut handler. Returns code that specifies both taken * actions and what should be done next. */ static KHandlerResponse trash_khandler(FileView *view, menu_data_t *m, const wchar_t keys[]) { if(wcscmp(keys, L"r") == 0) { return restore_current(m); } else if(wcscmp(keys, L"dd") == 0) { return delete_current(m); } return KHR_UNHANDLED; }
/* Set property 'pname' at node 'node' to value 'value' which has a length * of 'size' bytes. Return the number of bytes the prom accepted. */ int prom_setprop(int node, char *pname, char *value, int size) { unsigned long flags; int ret; if(size == 0) return 0; if((pname == 0) || (value == 0)) return 0; save_flags(flags); cli(); ret = prom_nodeops->no_setprop(node, pname, value, size); restore_current(); restore_flags(flags); return ret; }
/* Forth evaluate the expression contained in 'fstring'. */ void prom_feval(char *fstring) { unsigned long flags; if(!fstring || fstring[0] == 0) return; spin_lock_irqsave(&prom_lock, flags); if(prom_vers == PROM_V0) (*(romvec->pv_fortheval.v0_eval))(strlen(fstring), fstring); else (*(romvec->pv_fortheval.v2_eval))(fstring); restore_current(); spin_unlock_irqrestore(&prom_lock, flags); }
/* Return the length in bytes of property 'prop' at node 'node'. * Return -1 on error. */ int prom_getproplen(phandle node, const char *prop) { int ret; unsigned long flags; if((!node) || (!prop)) return -1; spin_lock_irqsave(&prom_lock, flags); ret = prom_nodeops->no_proplen(node, prop); restore_current(); spin_unlock_irqrestore(&prom_lock, flags); return ret; }
/* Query for input device type */ enum prom_input_device prom_query_input_device(void) { unsigned long flags; int st_p; char propb[64]; char *p; int propl; switch(prom_vers) { case PROM_V0: case PROM_V2: case PROM_SUN4: default: switch(*romvec->pv_stdin) { case PROMDEV_KBD: return PROMDEV_IKBD; case PROMDEV_TTYA: return PROMDEV_ITTYA; case PROMDEV_TTYB: return PROMDEV_ITTYB; default: return PROMDEV_I_UNK; }; case PROM_V3: spin_lock_irqsave(&prom_lock, flags); st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdin); restore_current(); spin_unlock_irqrestore(&prom_lock, flags); if(prom_node_has_property(st_p, "keyboard")) return PROMDEV_IKBD; if (prom_getproperty(st_p, "name", propb, sizeof(propb)) != -1) { if(strncmp(propb, "keyboard", sizeof("serial")) == 0) return PROMDEV_IKBD; } if (prom_getproperty(st_p, "device_type", propb, sizeof(propb)) != -1) { if(strncmp(propb, "serial", sizeof("serial"))) return PROMDEV_I_UNK; } propl = prom_getproperty(prom_root_node, "stdin-path", propb, sizeof(propb)); if(propl > 2) { p = propb; while(*p) p++; p -= 2; if(p[0] == ':') { if(p[1] == 'a') return PROMDEV_ITTYA; else if(p[1] == 'b') return PROMDEV_ITTYB; } } return PROMDEV_I_UNK; } }
/* Return the length in bytes of property 'prop' at node 'node'. * Return -1 on error. */ int prom_getproplen(int node, char *prop) { int ret; unsigned long flags; if((!node) || (!prop)) return -1; save_flags(flags); cli(); ret = prom_nodeops->no_proplen(node, prop); restore_current(); restore_flags(flags); return ret; }
/* Drop into the prom, with the chance to continue with the 'go' * prom command. */ void prom_cmdline(void) { extern void install_obp_ticker(void); extern void install_linux_ticker(void); unsigned long flags; spin_lock_irqsave(&prom_lock, flags); install_obp_ticker(); (*(romvec->pv_abort))(); restore_current(); install_linux_ticker(); spin_unlock_irqrestore(&prom_lock, flags); set_auxio(AUXIO_LED, 0); }
/* Acquire a property 'prop' at node 'node' and place it in * 'buffer' which has a size of 'bufsize'. If the acquisition * was successful the length will be returned, else -1 is returned. */ int prom_getproperty(phandle node, const char *prop, char *buffer, int bufsize) { int plen, ret; unsigned long flags; plen = prom_getproplen(node, prop); if((plen > bufsize) || (plen == 0) || (plen == -1)) return -1; /* Ok, things seem all right. */ spin_lock_irqsave(&prom_lock, flags); ret = prom_nodeops->no_getprop(node, prop, buffer); restore_current(); spin_unlock_irqrestore(&prom_lock, flags); return ret; }
/* Map physical device address 'paddr' in IO space 'ios' of size * 'num_bytes' to a virtual address, with 'vhint' being a hint to * the prom as to where you would prefer the mapping. We return * where the prom actually mapped it. */ char * prom_mapio(char *vhint, int ios, unsigned int paddr, unsigned int num_bytes) { unsigned long flags; char *ret; spin_lock_irqsave(&prom_lock, flags); if((num_bytes == 0) || (paddr == 0)) ret = (char *) 0x0; else ret = (*(romvec->pv_v2devops.v2_dumb_mmap))(vhint, ios, paddr, num_bytes); restore_current(); spin_unlock_irqrestore(&prom_lock, flags); return ret; }
/* Acquire a property 'prop' at node 'node' and place it in * 'buffer' which has a size of 'bufsize'. If the acquisition * was successful the length will be returned, else -1 is returned. */ int prom_getproperty(int node, char *prop, char *buffer, int bufsize) { int plen, ret; unsigned long flags; plen = prom_getproplen(node, prop); if((plen > bufsize) || (plen == 0) || (plen == -1)) return -1; /* Ok, things seem all right. */ save_flags(flags); cli(); ret = prom_nodeops->no_getprop(node, prop, buffer); restore_current(); restore_flags(flags); return ret; }
/* Close the device described by device handle 'dhandle'. */ int prom_devclose(int dhandle) { unsigned long flags; spin_lock_irqsave(&prom_lock, flags); switch(prom_vers) { case PROM_V0: (*(romvec->pv_v0devops.v0_devclose))(dhandle); break; case PROM_V2: case PROM_V3: (*(romvec->pv_v2devops.v2_dev_close))(dhandle); break; default: break; }; restore_current(); spin_unlock_irqrestore(&prom_lock, flags); return 0; }
/* Seek to specified location described by 'seekhi' and 'seeklo' * for device 'dhandle'. */ void prom_seek(int dhandle, unsigned int seekhi, unsigned int seeklo) { unsigned long flags; spin_lock_irqsave(&prom_lock, flags); switch(prom_vers) { case PROM_V0: (*(romvec->pv_v0devops.v0_seekdev))(dhandle, seekhi, seeklo); break; case PROM_V2: case PROM_V3: (*(romvec->pv_v2devops.v2_dev_seek))(dhandle, seekhi, seeklo); break; default: break; }; restore_current(); spin_unlock_irqrestore(&prom_lock, flags); return; }