diff -ru linux-2.4.17.ori/drivers/sound/trident.c linux-2.4.17/drivers/sound/trident.c --- linux-2.4.17.ori/drivers/sound/trident.c Tue Nov 13 14:19:41 2001 +++ linux-2.4.17/drivers/sound/trident.c Wed Jan 9 21:51:10 2002 @@ -36,6 +36,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * History + * v0.14.9e + * January 8 2002 Salvador E. Tropea (SET) + * added a /proc/driver/{vendor}/{card}/ac97-{number} entry * v0.14.9d * October 8 2001 Arnaldo Carvalho de Melo * use set_current_state, properly release resources on failure in @@ -3822,6 +3825,43 @@ return 0; } +static char driver_str[] = "driver/"; +static char ac97_str[] = "/ac97-0"; + +static const char *pci_id2name(u16 pci_id) +{ + const char *ret = "unknown"; + + switch (pci_id) + { + case PCI_DEVICE_ID_ALI_5451: + ret = "ali5451"; + break; + case PCI_DEVICE_ID_SI_7018: + ret = "sis7018"; + break; + case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX: + ret = "trident4D_DX"; + break; + case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX: + ret = "trident4D_NX"; + break; + case PCI_DEVICE_ID_INTERG_5050: + ret = "cyber5050"; + break; + } + + return ret; +} + +static void remove_proc_dirs(struct trident_card *card, const char *name, char *proc_str) +{ + sprintf(proc_str, "%s%s/%s", driver_str, name, card->pci_dev->slot_name); + remove_proc_entry(proc_str, NULL); + sprintf(proc_str, "%s%s", driver_str, name); + remove_proc_entry(proc_str, NULL); +} + /* AC97 codec initialisation. */ static int __init trident_ac97_init(struct trident_card *card) { @@ -3829,8 +3869,11 @@ unsigned long ready_2nd = 0; struct ac97_codec *codec; int i = 0; + char *proc_str; + const char *name; + int size_buf; + int proc_success = 0; - /* initialize controller side of AC link, and find out if secondary codes really exist */ switch (card->pci_id) @@ -3890,9 +3933,25 @@ break; } + /* Create a proc directory to inform about the codec facilities */ + name = pci_id2name(card->pci_id); + size_buf = sizeof(driver_str) + sizeof(ac97_str) + strlen(name) + + strlen(card->pci_dev->slot_name); /* Note: sizeof gives 1 extra for EOS and / */ + proc_str = (char *)vmalloc(size_buf); + sprintf(proc_str, "%s%s", driver_str, name); + if (proc_mkdir(proc_str, 0)) { + sprintf(proc_str, "%s%s/%s", driver_str, name, card->pci_dev->slot_name); + if (proc_mkdir(proc_str, 0)) + proc_success = 1; + } + strcat(proc_str, ac97_str); + size_buf = strlen(proc_str) - 1; + for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) { - if ((codec = kmalloc(sizeof(struct ac97_codec), GFP_KERNEL)) == NULL) + if ((codec = kmalloc(sizeof(struct ac97_codec), GFP_KERNEL)) == NULL) { + remove_proc_dirs(card, name, proc_str); return -ENOMEM; + } memset(codec, 0, sizeof(struct ac97_codec)); /* initialize some basic codec information, other fields will be filled @@ -3920,11 +3979,22 @@ card->ac97_codec[num_ac97] = codec; + /* Create a proc entry to inform about the codec facilities */ + if (proc_success) { + if (!create_proc_read_entry(proc_str, 0, 0, ac97_read_proc, codec)) + proc_success = 0; + proc_str[size_buf]++; /* after 10 codecs looks ugly, but works */ + } + /* if there is no secondary codec at all, don't probe any more */ if (!ready_2nd) break; } + vfree(proc_str); + if (!proc_success) + printk(KERN_WARNING "trident: cannot create /proc entry\n"); + if (card->pci_id == PCI_DEVICE_ID_ALI_5451) { for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) { if (card->ac97_codec[num_ac97] == NULL) @@ -4145,6 +4215,9 @@ { int i; struct trident_card *card = pci_get_drvdata(pci_dev); + int size_buf; + char *proc_str; + const char *name; /* * Kill running timers before unload. We can't have them @@ -4170,12 +4243,27 @@ free_irq(card->irq, card); release_region(card->iobase, 256); + name = pci_id2name(card->pci_id); + size_buf = sizeof(driver_str) + sizeof(ac97_str) + strlen(name) + + strlen(card->pci_dev->slot_name); /* Note: sizeof gives 1 extra for EOS */ + proc_str = (char *)vmalloc(size_buf); + sprintf(proc_str, "%s%s/%s%s", driver_str, name, card->pci_dev->slot_name, + ac97_str); + size_buf = strlen(proc_str) - 1; + /* unregister audio devices */ - for (i = 0; i < NR_AC97; i++) + for (i = 0; i < NR_AC97; i++) { if (card->ac97_codec[i] != NULL) { unregister_sound_mixer(card->ac97_codec[i]->dev_mixer); kfree (card->ac97_codec[i]); } + remove_proc_entry(proc_str, NULL); + proc_str[size_buf]++; + } + + remove_proc_dirs(card, name, proc_str); + vfree(proc_str); + unregister_sound_dsp(card->dev_audio); kfree(card);