Hi, (removed alsa-users from Cc since focused on the development only.)
At Mon, 02 Dec 2002 17:11:20 +0800, Alamy Liu wrote: > > I would like to take it. May I ? > But I need guidance. the geode driver seems having the followng additional files to the 0.5.10b driver tree: - include/geode.h - cards/card-geode.c - lowlevel/pci/geode.c - lowlevel/pci/duraudio.c - lowlevel/pci/5530_def.h - lowlevel/pci/5530_glb.h - lowlevel/pci/os_inc.h on the alsa 0.9.0 tree, you should create a driver code either into a single file - pci/geode.c or files under sub-directory - pci/geode/*.[ch] please note that even the card-specific header files should go into this sub-directory unless they need to be exported to user-space. after i took a further look at the codes, i found that there are many unnecessary parts in the files above. especially, most of duraudio.c shouldn't be used. it's evil. also, the macros in os_inc.h should be expanded, i.e. the standard functions instead of redefined macro should be used. because of these things, the porting may take longer than i expected... anyway, let me explain the first step. the basic structure of the code would be as same as other pci drivers. please check some driver sources. for example, es1938.c or maestro3.c are good example. both of them have the sources on 0.5.x tree, so you can compare the differences. you'll have *_init() function just calling pci_module_init() to register the pci_driver table which contains name, id_table, probe and remove pointers. also, *_exit() function to call pci_unregister_driver(). the real init part is done in *_probe() callback. there, check and increment the device index at first. then create a card: snd_card_new(). the chip-specific data are stored in a chip record. this can be allocated in two ways. 1) allocating via snd_card_new(). you can pass the extra-data-length to the 4th argument of snd_card_new(), i.e. card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(geode_t)) whether geode_t is the chip record. in return, the allocated record can be acceseed as geode_t *chip = (geode_t *)card->private_data; with this method, you don't have to allocate twice. but you cannot use "magic-cast" for this record pointer, instead. (see below) 2) allocating an extra device. after allocating a card instance via snd_card_new() (with NULL on the 4th arg), call snd_magic_kcalloc(). card = snd_card_new(index[dev], id[dev], THIS_MODULE, NULL); .... chip = snd_magic_kcalloc(geode_t, 0, GFP_KERNEL); chip->card = card; ... you need to define a magic-value for geode_t (in include/sndmagic.h) #define snd_usb_midi_in_endpoint_t_magic 0xa15a4501 the value is arbitrary but should be unique. initialize the fields, and register this chip record as a lowlevel device with a specifed ops, static snd_device_ops_t ops = { .dev_free = snd_geode_dev_free, }; snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); snd_geode_dev_free() is the device-destructor, which will call static int snd_geode_dev_free(snd_device_t *device) { geode_t *chip = snd_magic_cast(geode_t, device->device_data, return -ENXIO); return snd_geode_free(chip); } where snd_geode_free() is the real destructor. what is the advantage of the second method? as mentioned above, the second method allows a "magic-cast" for geode_t. if you have a void pointer (such like pcm->private_data), the pointer type is unknown at the compile time, and you cannot know even if a wrong pointer is passed. the magic-cast checks the pointer type at the runtime, so it's good for debugging. for casting a pointer, do like this: geode_t *chip = snd_magic_cast(geode_t, source_pointer, action); source_pointer is the pointer to be casted (e.g. pcm->private_data) action is the action to do if the cast fails (e.g. return -EINVAL). now you can check and allocate resources. don't forget to call pci_enable_device() before allocating resources. also you have to call pci_set_dma_mask() with 28bit mask (0x0fffffff) for geode chips. on 0.9.0, you don't need allocate DMA for PCI like 0.5.x. allocation of ports and irqs are done via standard kernel functions. unlike 0.5.x., there are no helpers for that. and these resources must be released in the destructor function (see below). when the resources are allocated, then we can create pcm and mixer stuffs. but let's take them later on and write a destructor at first. the role of destructor is simple: disable the hardware (if already activated) and release the resources. for releasing the resource, "check-and-release" method is a safer way. i.e. static int snd_geode_free(geode_t *chip) { if (chip->res_port) { release_resource(chip->res_port); kfree_nocheck(chip->res_port); } if (chip->irq >= 0) free_irq(chip->irq, (void *)chip); snd_magic_kfree(chip); return 0; } as you can see, the i/o resources are also to be freed via kfree_nocheck() after release_resource() is called. now, let's finish the pci_driver data. write a pci_device_id table for this chipset, static struct pci_device_id snd_geode_ids[] __devinitdata = { { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_UNICORN, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CENTAURUS, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, { PCI_VENDOR_ID_NSC, PCI_DEVICE_ID_CENTAURUS, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, { PCI_VENDOR_ID_NSC, PCI_DEVICE_ID_SCORPIUS, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, { 0, } }; MODULE_DEVICE_TABLE(pci, snd_geode_ids); and static struct pci_driver driver = { .name = "NSC/Cyrix Geode", .id_table = snd_geode_ids, .probe = snd_geode_probe, .remove = __devexit_p(snd_geode_remove), }; static int __init alsa_card_geode_init(void) { int err; if ((err = pci_module_init(&driver)) < 0) { #ifdef MODULE printk(KERN_ERR "NSC/Cyrix Geode soundcard not found or device busy\n"); #endif return err; } return 0; } static void __exit alsa_card_geode_exit(void) { pci_unregister_driver(&driver); } module_init(alsa_card_geode_init) module_exit(alsa_card_geode_exit) you can at least comple and build the module now (although not functional yet :) let's proceed to the pcm and ac97 part at next... ciao, Takashi ------------------------------------------------------- This sf.net email is sponsored by:ThinkGeek Welcome to geek heaven. http://thinkgeek.com/sf _______________________________________________ Alsa-devel mailing list [EMAIL PROTECTED] https://lists.sourceforge.net/lists/listinfo/alsa-devel