[eside-ghost] Que Comando??

yUnwEb yunweb en yunweb.homeunix.org
Mie Dic 21 10:20:37 CET 2005


On ar., 2005-12-20 at 23:04 +0100, Jon Ander Hernández wrote:
> Aupi!

Ieup!

> 
> On mar, 2005-12-20 at 21:33 +0100, yUnwEb wrote:
> > Aupa JonAn, cuanto tiempo :)
> 
> Bueno hace 2 o 3 semanas que escribí la última vez, pero escribí tanto
> que me dí un descanso, jejejeje.

Joer, pero es que se aprende un huevo con tus e-mails :P

Voy a hacer un esfuerzo y voy a intentar explicarme yo también un poco.

> 
> > He leido el hilo un poco rápido, pero si no he entendido mal puede que
> > /proc/bus/pci/devices pueda ayudaros. Es decir, si yo tengo por ejemplo
> > el módulo ehci_hcd para sacar su dispositivo haría algo del estilo de:
> > 
> > # MODULE=ehci_hcd; lspci -d $(grep -B 1 ${MODULE} /proc/bus/pci/devices|tail -1|awk '{print $2}'|sed 's/^\([0-9]\{4\}\)/\1:/')
> > 00:1d.7 USB Controller: Intel Corp. 82801DB (ICH4) USB2 EHCI Controller (rev 01)
> > 
> > Evidentemente esta guarrada sólo saca el primer dispositivo del módulo.
> > Ya que un módulo puede gobernar varios dispositivos. Pero vamos, os vale
> > para que os hagáis una idea :)
> 
> Desde luego sabes pero mucho, mucho más que yo de sed/grep/awk, que
> suerte tienes buahhh como te envidio xDDDDDDD. A ver si me pillo un buen
> libro o me meto entre pecho y espalda una buena guía :)
> 
> No conocía lo que había dentro de /proc/bus/pci/devices, es interesante,
> en mi caso no es de ayuda porque yo necesito saber cual es la relación
> entre módulo y dispositivo antes de cargar el módulo, y entiendo
> que /proc/bus/pci/devices es capaz de decirnos esta relación una vez que
> el módulo esta cargado y no antes.

Vale, de acuerdo. Entonces lo que tu dices sí que está
en /lib/modules/$(uname -r)/. Más concretamente en el fichero
modules.pcimap.

Al hacer un módulo o controlador, se utiliza la estructura pci_device_id
para comunicarle al núcleo que dispositivos soporta. Normalmente se hace
a traves de la macro PCI_DEVICE(vendorId, DeviceId). Y tú es lo que creo
que andas buscando.

/usr/include/linux/pci.h:
struct pci_device_id {
        unsigned int vendor, device;            /* Vendor and device ID
or PCI_ANY_ID */
        unsigned int subvendor, subdevice;      /* Subsystem ID's or
PCI_ANY_ID */
        unsigned int class, class_mask;         /*
(class,subclass,prog-if) triplet */
        unsigned long driver_data;              /* Data private to the
driver */
};

Según tengo entendido esta estructura se exporta al espacio de usuario a
traves de /lib/modules/$(uname -r)/modules.pcimap mediante la macro
MODULE_DEVICE_TABLE para el sistema hotplug y demás.

Es decir, por ejemplo, yo en el modulo ipw2100 tengo:
/usr/local/src/ipw2100-1.1.0/ipw2100.c:
#define IPW2100_DEV_ID(x) { PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, x }

static struct pci_device_id ipw2100_pci_id_table[] __devinitdata = {
        IPW2100_DEV_ID(0x2520), /* IN 2100A mPCI 3A */
        IPW2100_DEV_ID(0x2521), /* IN 2100A mPCI 3B */
        IPW2100_DEV_ID(0x2524), /* IN 2100A mPCI 3B */
        IPW2100_DEV_ID(0x2525), /* IN 2100A mPCI 3B */
        IPW2100_DEV_ID(0x2526), /* IN 2100A mPCI Gen A3 */
...
        IPW2100_DEV_ID(0x25A0), /* HP 2100 mPCI 3B */
        {0,},
};

MODULE_DEVICE_TABLE(pci, ipw2100_pci_id_table);

Esta macro añade un símbolo externo llamado "__mod_pci_device_table"
apuntando al pci_device_id en el módulo tal y como se puede ver en:

/usr/include/linux/module.h:
#define MODULE_GENERIC_TABLE(gtype,name)        \
static const unsigned long __module_##gtype##_size \
  __attribute_used__ = sizeof(struct gtype##_id); \
static const struct gtype##_id * __module_##gtype##_table \
  __attribute_used__ = name
...
#define MODULE_DEVICE_TABLE(type,name)          \
  MODULE_GENERIC_TABLE(type##_device,name)

Se puede ver que el ipw2100.ko tiene por ahí los
"__mod_pci_device_table":
# strings /lib/modules/2.6.11.9/kernel/drivers/net/wireless/ipw2100.ko|
grep "__mod_pci_device_table"
__mod_pci_device_table
__mod_pci_device_table
__mod_pci_device_table
# nm -g /lib/modules/2.6.11.9/kernel/drivers/net/wireless/ipw2100.ko|
grep "__mod_pci_device_table"
000003c0 D __mod_pci_device_table

Luego es el depmod el que se encarga de sacar esas variables de los
modulos de /lib/modules/$(uname -r)/ y meterlas en el modules.pcimap.

Échale una ojeada al "depmod -n", eso saca por pantalla los datos en vez
de escribirlos en /lib/modules/$(uname -r)/*

En /usr/src/module-init-tools-3.2/depmod.c:
static void parse_modules(struct module *list)
{
        struct module *i;

        for (i = list; i; i = i->next) {
                i->ops->load_symbols(i);
                i->ops->fetch_tables(i);
        }
}

A parse_modules se le llama desde el main de depmod. En fetch_tables se
lee el "__mod_pci_device_table".

/usr/src/module-init-tools-3.2/depmod.h:
struct module
{
        ...
        /* 64 or 32 bit? */
        struct module_ops *ops;
        ...
}

struct module_ops PERBIT(mod_ops) = {
        .load_symbols   = PERBIT(load_symbols),
        .calculate_deps = PERBIT(calculate_deps),
        .fetch_tables   = PERBIT(fetch_tables),
        .get_aliases    = PERBIT(get_aliases),
        .get_modinfo    = PERBIT(get_modinfo),
};

En /usr/src/module-init-tools-3.2/moduleops_core.c  se puede ver que
llama a una función PERBIT desde la que se lee el símbolo
"__mod_pci_device_table" desde la secciones ".symtab" y ".strtab" del
módulo

struct module_ops PERBIT(mod_ops) = {
        .load_symbols   = PERBIT(load_symbols),
        .calculate_deps = PERBIT(calculate_deps),
        .fetch_tables   = PERBIT(fetch_tables),
        .get_aliases    = PERBIT(get_aliases),
        .get_modinfo    = PERBIT(get_modinfo),
};
...
static void PERBIT(fetch_tables)(struct module *module)
{
        module->pci_size = PERBIT(PCI_DEVICE_SIZE);
        module->pci_table = PERBIT(deref_sym)(module->data,
                                        "__mod_pci_device_table",
                                        module->conv);
...

Bueno, que igual me he desviado un poco del tema. Total, que podría ser
algo tipo:

# MODULE=ipw2100; lspci -d $(grep "^${MODULE}" /lib/modules/$(uname
-r)/modules.pcimap|head -1|sed 's/0x0000//g'|awk '{print $2":"$3}')

Seguro que he que con tanto rollo he metido la pata en alguna parte o
se me escapa algo. Pero bueno, espero haberte acercado un poco más a la
solución con esto.

> 
> Supongo que si a Jon le vale saber la relación módulo-dispositivo y para
> el bus pci, entonces entiendo que tu solución es perfecta.

Perfecta para él, pero a ti no te valía ;)

> 
> En mi caso se que todo lo que necesito esta en ese script, el que he
> mandado. Ahora solo necesito saber más de bash/sed/grep/awk para
> entenderlo bien de pe a pa.

No lo he mirado, es que ahora mismo me da un poco de pereza.

> 
> Un saludete!!
> 
> JonAn.
> 
> P.D: De todas maneras hoy estoy espeso, creo que mis explicaciones de
> antes pueden haberle alejado innecesariamente a Jon de una solución
> simple. 
> Como dice azabel, la respuesta esta en los ficheros que están
> en /lib/modules/$(uname -r)/, y debería haberlo dicho al principio, solo
> que no se, me ha salido del alma dar toda la explicación de lo que había
> descubierto hasta ahora del tema.

Bueno, por hoy ya me vale.

Hasta la próxima :)

--
yUnwEb



Más información sobre la lista de distribución eside-ghost