static void proc_go(PD *p) { struct gouser_stack *sp; D(("BDOS: xexec - trying to load (and execute) a process on 0x%lx...\n", p->p_tbase)); p->p_parent = run; /* create a stack at the end of the TPA */ sp = (struct gouser_stack *) (p->p_hitpa - sizeof(struct gouser_stack)); sp->basepage = p; /* the stack contains the basepage */ sp->retaddr = p->p_tbase; /* return address a3 is text start */ sp->sr = get_sr() & 0x0700; /* the process will start in user mode, same IPL */ /* the other stack is the supervisor stack */ sp->other_sp = (long) &supstk[SUPSIZ]; /* store this new stack in the saved a7 field of the PD */ p->p_areg[7-3] = (long) sp; #if 1 /* the following settings are not documented, and hence theoretically * the assignments below are not necessary. * However, many programs test if A0 = 0 to check if they are running * as a normal program or as an accessory, so we need to clear at least * this register! */ { /* d1-d7/a0-a2 and dummy return address set to zero */ int i; for(i = 0; i < 11 ; i++) sp->fill[i] = 0; } p->p_areg[6-3] = (long) sp; /* a6 to hold a copy of the stack */ p->p_areg[5-3] = p->p_dbase; /* a5 to point to the DATA segt */ p->p_areg[4-3] = p->p_bbase; /* a4 to point to the BSS segt */ #endif /* the new process is the one to run */ run = (PD *) p; gouser(); }
int main(int argc, char **argv) { int optchar; int search = 0; char *drv = NULL; u_int16_t freq = DEF_FREQ; int volu = 0; u_int16_t action = NONE; u_int16_t lower = 0, higher = 0; u_int32_t cycle = 1; #ifndef NOMIXER int mixer = 0; char *master_volume = NULL; char *other_volume = NULL; #endif /* !NOMIXER */ if (gouser() < 0) return -1; pn = strrchr(argv[0], '/'); if (pn == NULL) pn = argv[0]; else pn++; radio_init(); /* * Call radio_drv_init() before usage(), * or default driver will be: NULL, 0x0 */ drv = getenv("FMTUNER"); if (drv == NULL || *drv == '\0') drv = DEF_DRV; if (radio_drv_init(drv) == ERADIO_INVL) invalid_driver_error(drv); if (argc < 2) usage(); /* Argh... options */ #ifndef NOMIXER while ((optchar = getopt(argc, argv, "c:Dd:f:h:il:mSsv:W:X:x:")) != -1) { #else while ((optchar = getopt(argc, argv, "c:Dd:f:h:il:mSsv:W:X:x:")) != -1) { #endif /* !NOMIXER */ switch (optchar) { case 'c': /* number of probes for each scanned frequency */ if ((cycle = strtol(optarg, (char **)NULL, 10)) == 0) cycle = 1; break; case 'D': action = DETE; break; case 'd': radio_drv_free(); if (radio_drv_init(optarg) == ERADIO_INVL) invalid_driver_error(optarg); break; case 'f': freq = 100.0 * strtod(optarg, (char **)NULL); if (freq == 0) freq = DEF_FREQ; action |= TUNE; break; case 'h': higher = atof(optarg) * 100; break; case 'i': action |= INFO; break; case 'l': lower = atof(optarg) * 100; break; case 'm': action |= MONO; break; case 'S': action = SCAN; break; case 's': action |= STAT; break; case 'v': volu = strtoul(optarg, (char **)NULL, 10); action |= VOLU; break; case 'W': action = SRCH; search = atof(optarg) * 100; break; #ifndef NOMIXER case 'X': /* set outputs.master */ master_volume = optarg; break; case 'x': other_volume = optarg; break; #endif /* !NOMIXER */ default: usage(); } } /* Minor actions have more priority */ if (action & MINOR) action &= MINOR; #if 0 /* Drop privs for drivers that don't need root */ if ((action & ~MINOR) != DETE) if (!radio_info_root()) setuid(getuid()); #endif /* Enabling communication with the radio port */ if (radio_info_root()) if (goroot() < 0) die(1); if (radio_get_port() < 0) die(1); /* Test for card presense */ if (radio_test_port() != 1) { fprintf(stderr, "%s: card not found: ", pn); radio_info_show(stderr, radio_info_name(), radio_info_port()); radio_free_port(); die(1); } if (radio_info_root()) if (gouser() < 0) die(1); /* * During time consuming actions fmio can get * some signal. Define action for such emergency. * Though it's more suitable to define these under SCAN or DETE, * it won't hurt if they'll be here. */ signal(SIGINT , die); #ifndef __DOS__ signal(SIGHUP , die); #endif signal(SIGTERM, die); switch (action & ~MINOR) { case NONE: #ifndef NOMIXER mixer = radio_mixer_init() < 0 ? 0 : 1; #endif /* !NOMIXER */ if (radio_info_root()) if (goroot() < 0) die(1); if (action & MONO) radio_set_mono(); switch (radio_info_policy()) { case 0: if (action & TUNE) radio_set_volume(action & VOLU ? volu : 1); break; case 1: if (action & TUNE) radio_set_volume(action & VOLU ? volu : radio_info_maxvol()); break; } if (action & TUNE) radio_set_freq(freq); if (action & VOLU) radio_set_volume(volu); if (action & STAT) { int st = radio_info_stereo(); int si = radio_info_signal(); if (st != ERADIO_INVL) printf("%s", st ? "stereo" : "mono"); if (st != ERADIO_INVL && si != ERADIO_INVL) printf(" : "); if (si != ERADIO_INVL) printf("%s", si ? "signal" : "noise"); if (st != ERADIO_INVL || si != ERADIO_INVL) printf("\n"); } if (action & INFO) { u_int16_t f = radio_info_freq(); int v = radio_info_volume(); printf("Driver: "); radio_info_show(stdout, radio_info_name(), radio_info_port()); if (f) printf("Frequency: %.2f MHz\n", (float) f / 100); if (v) printf("Volume: %u\n", v); v = radio_info_signal(); if (v != ERADIO_INVL) printf("Signal: %s\n", v ? "on" : "off"); v = radio_info_stereo(); if (v != ERADIO_INVL) printf("Stereo: %s\n", v ? "on" : "off"); } if (radio_info_root()) gouser(); #ifndef NOMIXER if (mixer) if (other_volume) radio_mixer_update_volume(other_volume); /* * Now outputs.master=0,0 * Update saved values */ if (mixer) { if (master_volume) radio_mixer_set_volume(master_volume); radio_mixer_cleanup(); } #endif /* !NOMIXER */ break; case DETE: if (goroot() < 0) die(1); radio_detect(); if (gouser() < 0) die(1); break; case SCAN: if (radio_info_root()) if (goroot() < 0) die(1); radio_scan(lower, higher, cycle); if (radio_info_root()) if (gouser() < 0) die(1); break; case SRCH: #ifndef NOMIXER mixer = radio_mixer_init() < 0 ? 0 : 1; #endif /* !NOMIXER */ if (radio_info_root()) if (goroot() < 0) die(1); if (search < 0) freq = radio_search(0, -1 * search); else freq = radio_search(1, search); if (radio_info_root()) if (gouser() < 0) die(1); if (freq) printf("%s: %.2f MHz\n", pn, (float)freq / 100); #ifndef NOMIXER if (mixer) radio_mixer_cleanup(); #endif /* !NOMIXER */ break; default: break; } if (radio_info_root()) if (goroot() < 0) die(1); radio_free_port(); if (radio_info_root()) gouser(); radio_drv_free(); radio_cleanup(); return 0; } /* * Dump the usage string to screen */ void usage(void) { const char usage_string[] = #ifdef NOMIXER "Usage: %s [-d driver] [-f frequency] [-i] [-m] [-s] [-v volume]\n" #else "Usage: %s [-d drv] [-f freq] [-i] [-m] [-s] [-v vol] [-X vol] [-x vol]\n" #endif /* NOMIXER */ "\t%s [-d driver] -S [-l begin] [-h end] [-c count]\n" "\t%s [-d driver] -W frequency\n" "\t%s -D - detect driver\n\n" "\t-f frequency in Mhz, -f 98.0 for example\n" "\t-i information\n" "\t-m mono\n" "\t-s stat\n" "\t-v volume, -v 0 set tuner off\n" "\t-S scan -l start frequency, -h end frequency\n" "\t-c number of probes for each scanned frequency\n" "\t-W search\n" ; printf("%s version %s\n", pn, VERSION); printf("Default driver: "); radio_info_show(stdout, radio_info_name(), radio_info_port()); printf(usage_string, pn, pn, pn, pn); die(0); } void die(int sig) { radio_drv_free(); radio_cleanup(); exit(sig); }