?? ltmodem.c,v
字號:
switch (id)
{
case PCI_CAP_ID_PM:
printf("Power Management version %d\n", cap & PCI_PM_CAP_VER_MASK);
break;
case PCI_CAP_ID_AGP:
break;
default:
printf("#%02x [%04x]", id, cap);
}
where = next;
}
}
}
d460 1a460 4static struct bus *
find_bus(struct bridge *b, unsigned int n)
{
struct bus *bus;
a461 4 for(bus=b->first_bus; bus; bus=bus->sibling)
if (bus->number == n)
break;
return bus;
d464 2a465 2static struct bus *
new_bus(struct bridge *b, unsigned int n)
a466 1 struct bus *bus = xmalloc(sizeof(struct bus));
d468 1a468 8 bus = xmalloc(sizeof(struct bus));
bus->number = n;
bus->sibling = b->first_bus;
bus->first_dev = NULL;
bus->last_dev = &bus->first_dev;
b->first_bus = bus;
return bus;
}
d470 1a470 5static void
insert_dev(struct device *d, struct bridge *b)
{
struct pci_dev *p = d->dev;
struct bus *bus;
d472 1a472 39 if (! (bus = find_bus(b, p->bus)))
{
struct bridge *c;
for(c=b->child; c; c=c->next)
if (c->secondary <= p->bus && p->bus <= c->subordinate)
return insert_dev(d, c);
bus = new_bus(b, p->bus);
}
/* Simple insertion at the end _does_ guarantee the correct order as the
* original device list was sorted by (bus, devfn) lexicographically
* and all devices on the new list have the same bus number.
*/
*bus->last_dev = d;
bus->last_dev = &d->next;
d->next = NULL;
}
/* Bus mapping mode */
static void
do_map_bridges(int bus, int min, int max)
{
struct bus_info *bi = bus_info + bus;
struct bus_bridge *b;
bi->guestbook = 1;
for(b=bi->bridges; b; b=b->next)
{
if (bus_info[b->first].guestbook)
b->bug = 1;
else if (b->first < min || b->last > max)
b->bug = 2;
else
{
bus_info[b->first].via = b;
do_map_bridges(b->first, b->first, b->last);
}
}
}
d474 2d477 4a480 21/* Show hexadecimal dump of first 64 bytes of the PCI configuration space
(the standard header). Useful for debugging of drivers and lspci itself. */
static void
show_hex_dump(struct device *d)
{
unsigned int i;
printf("Command reg: ");
printf(" %02x", get_conf_byte(d, 5));
printf(" %02x", get_conf_byte(d, 4));
putchar('\t');
printf("Status reg: ");
printf(" %02x", get_conf_byte(d, 7));
printf(" %02x", get_conf_byte(d, 6));
putchar('\n');
/* Note! the byte order is lsb msb */
printf("Base address regs: ");
for(i=0x10; i<0x24; i++){
printf(" %02x", get_conf_byte(d, i));
d482 1a482 2 putchar('\n');
a484 6// Lucent modem specific stuff.
void go_onhook(void)
{
dp_onhook_cmd();
}
a485 13void io_init(void)
{
// Set up the port IO.
port_io_init(io_address[1], io_address[2]);
// Set up EEPROM ?
//SetUpEEPROM();
// Set up the modem variables etc.
MimicInit();
}
@1.4log@Included Pavel's updates and tidy ups.@text@d1 927a927 923/* * $Id: ltmodem.c,v 1.3 1999/07/21 03:30:34 root Exp root $ * * Lucent PCI modem diagnostics tool. * * Copyright (c) 1999 Richard J.M. Close * Copyright (c) 1999 Pavel Machek <pavel@@ucw.cz> * * Can be freely distributed and used under the terms of the GNU GPL. */#include "ltmodem.h"unsigned int portbase;unsigned int modem_irq;int verbose = 0;/* Main program. */int main(int argc, char **argv){ char c; sync(); /* it's for your own protection */ setvbuf(stdout, NULL, _IONBF, 0); puts("ltmodem version " LTMODEM_VERSION); modem = 0; io_cnt = 0; pacc = pci_alloc(); pacc->error = die; pci_filter_init(pacc, &filter); pci_init(pacc); scan_devices(); sort_them(); /* If modem is found then it sets modem_dev to device structure for modem, and modem =1 */ if ( !find_modem() ) { printf ("Sorry, no Lucent PCI modem that I know of was found.\n"); printf ("If you have one fitted then please mail me with the details\n"); printf ("at: richard@@close.u-net.com please include an output from\n"); printf ("cat /proc/pci and as much info. on the card as possible.\n"); exit(1); } while ((c = getopt(argc, argv, "imovth" )) != -1) { switch(c) { case 'i': show_modem(); main_menu(); break; case 't': show_modem(); setup_irq(); io_init(); dp_change_mercury_gain(0x88, 0x80, 0x6b, 0x1e); sleep(1); dp_change_mercury_gain(0x88, 0x80, 0x6b, 0x7e); sleep(1); dp_change_mercury_gain(0x88, 0x80, 0x6b, 0x1e); sleep(1); dp_change_mercury_gain(0x88, 0x80, 0x6b, 0xff); sleep(1); dp_change_mercury_gain(0x88, 0x80, 0x6b, 0x00); sleep(1); dp_change_mercury_gain(0x88, 0x80, 0x6b, 0x25); sleep(1); dp_change_mercury_gain(0x88, 0x80, 0x6b, 0x89); sleep(1); dp_change_mercury_gain(0x88, 0x80, 0x6b, 0x1e); sleep(1); break; case 'o': show_modem(); setup_irq(); io_init(); //dp_offhook_cmd(); /* go_offhook(); -- seems to do something slightly different */#if 0 while(1) { printf( "%4x %4x %4x %4x %4x %4x\n", readbio(0x1002), readbio(0x1120), readbio(0xffff), readbio(0xf0ff), readbio(0xf1ff), readbio(0xf2ff)); sleep(1); }#endif break; case 'm': continous_monitoring(3, 1000); break; case 'v': verbose++; break; case 'h': default: printf( "Usage: ltmodem [-imovt]\n" ); printf( "-i interative use.\n-m monitoring ports/registers.\n"); printf( "-o run offhook command.\n-v increase level of verbosity.\n"); printf( "-t mess around with mercury gain (whatever that is). \n"); goto exit; } } exit: pci_cleanup(pacc); return 0;}voidsetup_irq(void){ printf( "Removing i2sig\n" ); system("rmmod i2sig"); // Setup IRQ variable used by other stuff. modem_irq = modem_dev->dev->irq;#if 0 char buf[10240]; sprintf( buf, "insmod ./i2sig.o irq=%d pid=%d", modem_irq, getpid()); printf( "Installing new i2sig: %s\n", buf ); system(buf);#endif signal_init();}/* Find any known any Lucent modems. */static intfind_modem(void){ struct device *d; int i; for(d=first_dev; d; d=d->next) { struct pci_dev *p = d->dev; /* Only cards with vendor ID = Lucent!. */ if (p->vendor_id == 0x11c1) { modem_dev = d; modem = 1; io_cnt = 0; /* Record I/O addresses. */ for(i=0; i<htype0_cnt; i++){ pciaddr_t pos = p->base_addr[i]; u32 flg = get_conf_long(d, PCI_BASE_ADDRESS_0 + 4*i); if (flg == 0xffffffff) flg = 0; if (!pos && !flg) continue; if (flg & PCI_BASE_ADDRESS_SPACE_IO) { io_address[i] = pos & PCI_BASE_ADDRESS_IO_MASK; io_length[i] = (io_address[i] < 0x3f8) ? 8 : 256; io_cnt = i; } } } } return modem;}// Show any found modem.static void show_modem(void){ int c; struct pci_dev *p = modem_dev->dev; byte classbuf[128], devbuf[128]; unsigned int irq = p->irq; byte latency = get_conf_byte( modem_dev, PCI_LATENCY_TIMER); word status = get_conf_word( modem_dev, PCI_STATUS); word cmd = get_conf_word( modem_dev, PCI_COMMAND); byte max_lat, min_gnt; word subsys_v, subsys_d; char ssnamebuf[256]; printf("%02x:%02x.%x %s: %s", p->bus, p->dev, p->func, pci_lookup_name(pacc, classbuf, sizeof(classbuf), PCI_LOOKUP_CLASS, get_conf_word( modem_dev, PCI_CLASS_DEVICE), 0), pci_lookup_name(pacc, devbuf, sizeof(devbuf), PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE, p->vendor_id, p->device_id)); if (c = get_conf_byte( modem_dev, PCI_REVISION_ID)) printf(" (rev %02x)", c); if (c = get_conf_byte( modem_dev, PCI_CLASS_PROG)) printf(" (prog-if %02x)", c); putchar('\n'); max_lat = get_conf_byte( modem_dev, PCI_MAX_LAT); min_gnt = get_conf_byte( modem_dev, PCI_MIN_GNT); subsys_v = get_conf_word( modem_dev, PCI_SUBSYSTEM_VENDOR_ID); subsys_d = get_conf_word( modem_dev, PCI_SUBSYSTEM_ID); if (subsys_v && subsys_v != 0xffff) printf("\tSubsystem: %s\n", pci_lookup_name(pacc, ssnamebuf, sizeof(ssnamebuf), PCI_LOOKUP_SUBSYSTEM | PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE, subsys_v, subsys_d)); printf("\tFlags: "); if (cmd & PCI_COMMAND_MASTER) printf("bus master, "); if (cmd & PCI_COMMAND_VGA_PALETTE) printf("VGA palette snoop, "); if (cmd & PCI_COMMAND_WAIT) printf("stepping, "); if (cmd & PCI_COMMAND_FAST_BACK) printf("fast Back2Back, "); if (status & PCI_STATUS_66MHZ) printf("66Mhz, "); if (status & PCI_STATUS_UDF) printf("user-definable features, "); printf("%s devsel", ((status & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_SLOW) ? "slow" : ((status & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_MEDIUM) ? "medium" : ((status & PCI_STATUS_DEVSEL_MASK) == PCI_STATUS_DEVSEL_FAST) ? "fast" : "??"); if (cmd & PCI_COMMAND_MASTER) printf(", latency %d", latency); if (irq) printf(", IRQ " IRQ_FORMAT, irq); putchar('\n'); show_htype0( modem_dev);}// Modem monitoring functions.voidmonitor_modem(void){ // Value input by user. char input = 'z'; // Monitoring activity type: // registers = 1, I/O = 2. int monitor_type = 1; // Monitoring period in milliseconds, defaults to one second. int monitoring_interval = 1000; while (input != 'Q') { // Ignore the newline char. if (input != '\n') { printf ("***************************************************\n"); printf ("monitoring menu (Monitor monitorIo monitorRegs monitorBoth iNterval Quit): "); } // Get user input in uppercase. input = toupper (getchar()); switch (input) { case 'M': continous_monitoring(monitor_type, monitoring_interval); break; case 'I': printf( "Will monitor I/O ports.\n" ); monitor_type = 2; break; case 'R': printf( "Will monitor PCI registers.\n" ); monitor_type = 1; break; case 'B': printf( "Will monitor I/O ports and PCI registers.\n" ); monitor_type = 3; break; case 'N': monitoring_interval = set_monitoring_interval(); break; case '\n': break; case 'Q': break; default: printf ("Illegal option: %c\n", input); } }}int set_monitoring_interval(void){ // Value input by user. int input = 0; char trash; // Allow user to set interval. printf ("Set monitoring interval (in miliseconds): "); scanf ("%d%c", &input, &trash); if (input > 0) { // Return the user's value. printf ("Interval set to %d milliseconds.\n", input); return input; } else { // Default to one second. printf ("Illegal interval, using 1 second default.\n"); return 1000; }}void continous_monitoring(int monitor_type, int monitoring_interval){ // Iteration loop variable. unsigned int i; // Main monitoring loop. while (1) { // Monitor registers or I/O depending on current setting. if (monitor_type & 1) { // Re-scan device. pci_scan_bus(pacc); modem_dev = scan_device(modem_dev->dev); // Show the hex. show_hex_dump(modem_dev); } if (monitor_type & 2) { // Get access to all of I/O space. if (iopl(3) < 0) { perror("ltmodem: iopl()"); fprintf(stderr, "This program must be run as root.\n"); } else { // Read the ports. printf("I/O ports\n "); // Loop for each known port. for (i=1;i<=io_cnt;i++) { unsigned int j; printf( "%x: ", io_address[i] ); for (j=0; j<io_length[i]; j++) { // Read each byte, one at a time. printf("%2x ", inb(io_address[i] + j)); if ( !((j+1)%16) ) printf( "\n%x: ", io_address[i] + j + 1); } putchar('\n'); } // Free the ports. iopl(0); } } // Wait for the configured amount of time. usleep(monitoring_interval * 1000); }}/* Modem writing functions. */voidset_modem(void){ /* value input by user. */ char input = ' '; /* start by just doing a hex dump. */ show_hex_dump(modem_dev); /* Offer the user a choice of what to set. */ while (input != 'Q') { // Ignore newline character. if (input != '\n') { printf ("modem write (Controlreg Io Quit): "); } input = toupper (getchar ()); switch (input) { case 'C': set_modem_cont_reg(); redisplay_modem_regs(); break; case 'I': set_modem_io(); break; case '\n': break; case 'Q': break; default: printf ("Illegal option: %c\n", input); } }}void redisplay_modem_regs(void) { /* Re-scan device. */ printf ("Registers now contain:\n"); pci_scan_bus(pacc); modem_dev = scan_device(modem_dev->dev); /* Show the hex. */ show_hex_dump(modem_dev); }voidset_modem_cont_reg(void) { /* value input by user. */ int input = 0; /* CR input after first char. */ char trash; /* Allow user to set control register. */ printf ("Set control register (value in hex): "); scanf ("%x%c", &input, &trash); printf ("Writing %x to control register.\n", input); /* command register is at address 04. */ pci_write_word(modem_dev->dev, 0x04, input); }voidset_modem_io(void) { unsigned int i; /* value input by user. */ unsigned int input = 0; unsigned int offset = 0; /* CR input after first char. */ char trash; if (io_cnt > 0) { printf("I/O ports found:\n"); for(i=1; i<=io_cnt; i++){ printf("%d - I/O port at %x.\n", i, io_address[i]); } // Select the port. printf ("Port to write long word at (in hex): "); scanf ("%x%c", &input, &trash); // Write the value. if ((input > 0) && (input <= io_cnt)) { // Allow user to write to selected I/O port. i = input; printf ("Write to %x, enter value (in hex): ", io_address[i]); scanf ("%x%c", &input, &trash); // Get offset to use. printf ("Offset to use (in hex): "); scanf ("%x%c", &offset, &trash); printf ("Writing %2x to I/O port %x + %x.\n", input, io_address[i], offset); // Write value to port. WRITE_PORT_UCHAR ((io_address[i] + offset), input); ///* Delay 10ms. */ usleep(10000); /* Read back the port. */ printf("Read back value: %2x.\n", READ_PORT_UCHAR(io_address[i] + offset)); } } }/* Main command menu. */voidmain_menu(void){ /* char input by user. */ char input = 'z'; while (input != 'Q') { // Ignore the newline char. if (input != '\n') { printf ("main menu (Monitor Write Quit): "); } // Get user input in uppercase. input = toupper (getchar()); switch (input) { case 'M': monitor_modem(); break; case 'W': set_modem(); break; case '\n': break; case 'Q': break; default: printf ("Illegal option: %c\n", input); } } /* Bye bye... */ printf ("User stopped ltmodem.\n");}/********************************************************************************** PCI utilities.**********************************************************************************/static struct device *scan_device(struct pci_dev *p){ int how_much = 0x40; /* First 64 bytes. */ struct device *d; if (!pci_filter_match(&filter, p)) return NULL; d = xmalloc(sizeof(struct device)); bzero(d, sizeof(*d)); d->dev = p;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -