Date: Mon, 23 Jul 2007 23:39:05 GMT From: Christopher Davis <loafier@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 123985 for review Message-ID: <200707232339.l6NNd5rh035088@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=123985 Change 123985 by loafier@chrisdsoc on 2007/07/23 23:38:49 Use bus_alloc_resources(), pci_enable_busmaster(), etc. The driver was missing detach, suspend and resume methods. I added detatch method here, but I don't know what to send to the card to shut it down. Haven't tested this. Affected files ... .. //depot/projects/soc2007/loafier_busalloc/src/sys/dev/sound/pci/aureal.c#2 edit Differences ... ==== //depot/projects/soc2007/loafier_busalloc/src/sys/dev/sound/pci/aureal.c#2 (text+ko) ==== @@ -66,12 +66,31 @@ int dir; }; +/* XXX: seems like the driver only makes use of one port */ + +enum { + RES_P0, + RES_IRQ, + RES_SZ +}; + +static struct resource_spec au_res_spec_mem[] = { + {SYS_RES_MEMORY, PCIR_BAR(0), RF_ACTIVE}, + {SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHARABLE} +}; + +static struct resource_spec au_res_spec_io[] = { + {SYS_RES_IOPORT, PCIR_BAR(0), RF_ACTIVE}, + {SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHARABLE} +}; + struct au_info { int unit; + + struct resource_spec *spec; + struct resource *res[RES_SZ]; + void *ih; - bus_space_tag_t st[3]; - bus_space_handle_t sh[3]; - bus_dma_tag_t parent_dmat; struct mtx *lock; @@ -86,36 +105,13 @@ /* -------------------------------------------------------------------- */ -static u_int32_t -au_rd(struct au_info *au, int mapno, int regno, int size) -{ - switch(size) { - case 1: - return bus_space_read_1(au->st[mapno], au->sh[mapno], regno); - case 2: - return bus_space_read_2(au->st[mapno], au->sh[mapno], regno); - case 4: - return bus_space_read_4(au->st[mapno], au->sh[mapno], regno); - default: - return 0xffffffff; - } -} +#define au_rd1(_sc, _reg) bus_read_1((_sc)->res[RES_P0], _reg) +#define au_rd2(_sc, _reg) bus_read_2((_sc)->res[RES_P0], _reg) +#define au_rd4(_sc, _reg) bus_read_4((_sc)->res[RES_P0], _reg) -static void -au_wr(struct au_info *au, int mapno, int regno, u_int32_t data, int size) -{ - switch(size) { - case 1: - bus_space_write_1(au->st[mapno], au->sh[mapno], regno, data); - break; - case 2: - bus_space_write_2(au->st[mapno], au->sh[mapno], regno, data); - break; - case 4: - bus_space_write_4(au->st[mapno], au->sh[mapno], regno, data); - break; - } -} +#define au_wr1(_sc, _reg, _val) bus_write_1((_sc)->res[RES_P0], _reg, _val) +#define au_wr2(_sc, _reg, _val) bus_write_2((_sc)->res[RES_P0], _reg, _val) +#define au_wr4(_sc, _reg, _val) bus_write_4((_sc)->res[RES_P0], _reg, _val) /* -------------------------------------------------------------------- */ @@ -126,9 +122,9 @@ int i=0, j=0; regno<<=16; - au_wr(au, 0, AU_REG_CODECIO, regno, 4); + au_wr4(au, AU_REG_CODECIO, regno); while (j<50) { - i=au_rd(au, 0, AU_REG_CODECIO, 4); + i=au_rd4(au, AU_REG_CODECIO); if ((i & 0x00ff0000) == (regno | 0x00800000)) break; DELAY(j * 200 + 2000); j++; @@ -146,13 +142,13 @@ i=j=tries=0; do { while (j<50 && (i & AU_CDC_WROK) == 0) { - i=au_rd(au, 0, AU_REG_CODECST, 4); + i=au_rd4(au, AU_REG_CODECST); DELAY(2000); j++; } if (j==50) printf("codec timeout during write of register %x, data %x\n", regno, data); - au_wr(au, 0, AU_REG_CODECIO, (regno<<16) | AU_CDC_REGSET | data, 4); + au_wr4(au, AU_REG_CODECIO, (regno<<16) | AU_CDC_REGSET | data); /* DELAY(20000); i=au_rdcd(au, regno); */ tries++; @@ -188,8 +184,8 @@ int j = 0x1099c+(a<<2); if (au->x[a] != a+0x67) j = AU_REG_RTBASE+(au->x[a]<<2); - au_wr(au, 0, AU_REG_RTBASE+(route<<2), 0xffffffff, 4); - au_wr(au, 0, j, route | (b<<7), 4); + au_wr4(au, AU_REG_RTBASE+(route<<2), 0xffffffff); + au_wr4(au, j, route | (b<<7)); au->y[route]=au->x[a]; au->x[a]=route; au->z[route]=a & 0x000000ff; @@ -204,10 +200,10 @@ au_setbit(au->routes, route, 0); au->z[route]=0x1f; - i=au_rd(au, 0, AU_REG_RTBASE+(route<<2), 4); - au_wr(au, 0, AU_REG_RTBASE+(au->y[route]<<2), i, 4); + i=au_rd4(au, AU_REG_RTBASE+(route<<2)); + au_wr4(au, AU_REG_RTBASE+(au->y[route]<<2), i); au->y[i & 0x7f]=au->y[route]; - au_wr(au, 0, AU_REG_RTBASE+(route<<2), 0xfffffffe, 4); + au_wr4(au, AU_REG_RTBASE+(route<<2), 0xfffffffe); if (au->x[j] == route) au->x[j]=au->y[route]; au->y[route]=0x7f; } @@ -215,8 +211,8 @@ static void au_encodec(struct au_info *au, char channel) { - au_wr(au, 0, AU_REG_CODECEN, - au_rd(au, 0, AU_REG_CODECEN, 4) | (1 << (channel + 8)), 4); + au_wr4(au, AU_REG_CODECEN, + au_rd4(au, AU_REG_CODECEN) | (1 << (channel + 8))); } static void @@ -224,7 +220,7 @@ { u_int32_t i; - for (i=0; i<32; i++) au_wr(au, 0, AU_REG_FIFOBASE+(c<<7)+(i<<2), 0, 4); + for (i=0; i<32; i++) au_wr4(au, AU_REG_FIFOBASE+(c<<7)+(i<<2), 0); } static void @@ -232,10 +228,10 @@ { int x; - x = au_rd(au, 0, AU_REG_ADB, 4); + x = au_rd4(au, AU_REG_ADB); x &= ~(1 << c); x |= (enable << c); - au_wr(au, 0, AU_REG_ADB, x, 4); + au_wr4(au, AU_REG_ADB, x); } static void @@ -245,9 +241,9 @@ int i, stereo = (format & AFMT_STEREO)? 1 : 0; u_int32_t baseaddr = sndbuf_getbufaddr(ch->buffer); - au_wr(au, 0, 0x1061c, 0, 4); - au_wr(au, 0, 0x10620, 0, 4); - au_wr(au, 0, 0x10624, 0, 4); + au_wr4(au, 0x1061c, 0); + au_wr4(au, 0x10620, 0); + au_wr4(au, 0x10624, 0); switch(format & ~AFMT_STEREO) { case 1: i=0xb000; @@ -264,28 +260,28 @@ default: i=0x3000; } - au_wr(au, 0, 0x10200, baseaddr, 4); - au_wr(au, 0, 0x10204, baseaddr+0x1000, 4); - au_wr(au, 0, 0x10208, baseaddr+0x2000, 4); - au_wr(au, 0, 0x1020c, baseaddr+0x3000, 4); + au_wr4(au, 0x10200, baseaddr); + au_wr4(au, 0x10204, baseaddr+0x1000); + au_wr4(au, 0x10208, baseaddr+0x2000); + au_wr4(au, 0x1020c, baseaddr+0x3000); - au_wr(au, 0, 0x10400, 0xdeffffff, 4); - au_wr(au, 0, 0x10404, 0xfcffffff, 4); + au_wr4(au, 0x10400, 0xdeffffff); + au_wr4(au, 0x10404, 0xfcffffff); - au_wr(au, 0, 0x10580, i, 4); + au_wr4(au, 0x10580, i); - au_wr(au, 0, 0x10210, baseaddr, 4); - au_wr(au, 0, 0x10214, baseaddr+0x1000, 4); - au_wr(au, 0, 0x10218, baseaddr+0x2000, 4); - au_wr(au, 0, 0x1021c, baseaddr+0x3000, 4); + au_wr4(au, 0x10210, baseaddr); + au_wr4(au, 0x10214, baseaddr+0x1000); + au_wr4(au, 0x10218, baseaddr+0x2000); + au_wr4(au, 0x1021c, baseaddr+0x3000); - au_wr(au, 0, 0x10408, 0x00fff000 | 0x56000000 | 0x00000fff, 4); - au_wr(au, 0, 0x1040c, 0x00fff000 | 0x74000000 | 0x00000fff, 4); + au_wr4(au, 0x10408, 0x00fff000 | 0x56000000 | 0x00000fff); + au_wr4(au, 0x1040c, 0x00fff000 | 0x74000000 | 0x00000fff); - au_wr(au, 0, 0x10584, i, 4); + au_wr4(au, 0x10584, i); - au_wr(au, 0, 0x0f800, stereo? 0x00030032 : 0x00030030, 4); - au_wr(au, 0, 0x0f804, stereo? 0x00030032 : 0x00030030, 4); + au_wr4(au, 0x0f800, stereo? 0x00030032 : 0x00030030); + au_wr4(au, 0x0f804, stereo? 0x00030032 : 0x00030030); au_addroute(au, 0x11, 0, 0x58); au_addroute(au, 0x11, stereo? 0 : 1, 0x59); @@ -345,8 +341,8 @@ if (ch->dir == PCMDIR_PLAY) { au_setadb(au, 0x11, (go)? 1 : 0); if (go != PCMTRIG_START) { - au_wr(au, 0, 0xf800, 0, 4); - au_wr(au, 0, 0xf804, 0, 4); + au_wr4(au, 0xf800, 0); + au_wr4(au, 0xf804, 0); au_delroute(au, 0x58); au_delroute(au, 0x59); } @@ -361,7 +357,7 @@ struct au_chinfo *ch = data; struct au_info *au = ch->parent; if (ch->dir == PCMDIR_PLAY) { - return au_rd(au, 0, AU_REG_UNK2, 4) & (AU_BUFFSIZE-1); + return au_rd4(au, AU_REG_UNK2) & (AU_BUFFSIZE-1); } else { return 0; } @@ -395,21 +391,21 @@ u_int32_t intsrc, i; au->interrupts++; - intsrc=au_rd(au, 0, AU_REG_IRQSRC, 4); + intsrc=au_rd4(au, AU_REG_IRQSRC); printf("pcm%d: interrupt with src %x\n", au->unit, intsrc); if (intsrc & AU_IRQ_FATAL) printf("pcm%d: fatal error irq\n", au->unit); if (intsrc & AU_IRQ_PARITY) printf("pcm%d: parity error irq\n", au->unit); if (intsrc & AU_IRQ_UNKNOWN) { - (void)au_rd(au, 0, AU_REG_UNK1, 4); - au_wr(au, 0, AU_REG_UNK1, 0, 4); - au_wr(au, 0, AU_REG_UNK1, 0x10000, 4); + (void)au_rd4(au, AU_REG_UNK1); + au_wr4(au, AU_REG_UNK1, 0); + au_wr4(au, AU_REG_UNK1, 0x10000); } if (intsrc & AU_IRQ_PCMOUT) { - i=au_rd(au, 0, AU_REG_UNK2, 4) & (AU_BUFFSIZE-1); + i=au_rd4(au, AU_REG_UNK2) & (AU_BUFFSIZE-1); chn_intr(au->pch.channel); - (void)au_rd(au, 0, AU_REG_UNK3, 4); - (void)au_rd(au, 0, AU_REG_UNK4, 4); - (void)au_rd(au, 0, AU_REG_UNK5, 4); + (void)au_rd4(au, AU_REG_UNK3); + (void)au_rd4(au, AU_REG_UNK4); + (void)au_rd4(au, AU_REG_UNK5); } /* don't support midi if (intsrc & AU_IRQ_MIDI) { @@ -424,8 +420,8 @@ } } */ - au_wr(au, 0, AU_REG_IRQSRC, intsrc & 0x7ff, 4); - au_rd(au, 0, AU_REG_IRQSRC, 4); + au_wr4(au, AU_REG_IRQSRC, intsrc & 0x7ff); + au_rd4(au, AU_REG_IRQSRC); } @@ -438,48 +434,48 @@ { u_int32_t i, j; - au_wr(au, 0, AU_REG_IRQGLOB, 0xffffffff, 4); + au_wr4(au, AU_REG_IRQGLOB, 0xffffffff); DELAY(100000); /* init codec */ /* cold reset */ for (i=0; i<32; i++) { - au_wr(au, 0, AU_REG_CODECCHN+(i<<2), 0, 4); + au_wr4(au, AU_REG_CODECCHN+(i<<2), 0); DELAY(10000); } if (1) { - au_wr(au, 0, AU_REG_CODECST, 0x8068, 4); + au_wr4(au, AU_REG_CODECST, 0x8068); DELAY(10000); - au_wr(au, 0, AU_REG_CODECST, 0x00e8, 4); + au_wr4(au, AU_REG_CODECST, 0x00e8); DELAY(10000); } else { - au_wr(au, 0, AU_REG_CODECST, 0x00a8, 4); + au_wr4(au, AU_REG_CODECST, 0x00a8); DELAY(100000); - au_wr(au, 0, AU_REG_CODECST, 0x80a8, 4); + au_wr4(au, AU_REG_CODECST, 0x80a8); DELAY(100000); - au_wr(au, 0, AU_REG_CODECST, 0x80e8, 4); + au_wr4(au, AU_REG_CODECST, 0x80e8); DELAY(100000); - au_wr(au, 0, AU_REG_CODECST, 0x80a8, 4); + au_wr4(au, AU_REG_CODECST, 0x80a8); DELAY(100000); - au_wr(au, 0, AU_REG_CODECST, 0x00a8, 4); + au_wr4(au, AU_REG_CODECST, 0x00a8); DELAY(100000); - au_wr(au, 0, AU_REG_CODECST, 0x00e8, 4); + au_wr4(au, AU_REG_CODECST, 0x00e8); DELAY(100000); } /* init */ for (i=0; i<32; i++) { - au_wr(au, 0, AU_REG_CODECCHN+(i<<2), 0, 4); + au_wr4(au, AU_REG_CODECCHN+(i<<2), 0); DELAY(10000); } - au_wr(au, 0, AU_REG_CODECST, 0xe8, 4); + au_wr4(au, AU_REG_CODECST, 0xe8); DELAY(10000); - au_wr(au, 0, AU_REG_CODECEN, 0, 4); + au_wr4(au, AU_REG_CODECEN, 0); /* setup codec */ i=j=0; while (j<100 && (i & AU_CDC_READY)==0) { - i=au_rd(au, 0, AU_REG_CODECST, 4); + i=au_rd4(au, AU_REG_CODECST); DELAY(1000); j++; } @@ -490,16 +486,16 @@ for (i=0; i<32; i++) au->x[i]=i+0x67; for (i=0; i<128; i++) au->y[i]=0x7f; for (i=0; i<128; i++) au->z[i]=0x1f; - au_wr(au, 0, AU_REG_ADB, 0, 4); - for (i=0; i<124; i++) au_wr(au, 0, AU_REG_RTBASE+(i<<2), 0xffffffff, 4); + au_wr4(au, AU_REG_ADB, 0); + for (i=0; i<124; i++) au_wr4(au, AU_REG_RTBASE+(i<<2), 0xffffffff); /* test */ - i=au_rd(au, 0, 0x107c0, 4); + i=au_rd4(au, 0, 0x107c0); if (i!=0xdeadbeef) device_printf(dev, "dma check failed: 0x%x\n", i); /* install mixer */ - au_wr(au, 0, AU_REG_IRQGLOB, - au_rd(au, 0, AU_REG_IRQGLOB, 4) | AU_IRQ_ENABLE, 4); + au_wr4(au, AU_REG_IRQGLOB, + au_rd4(au, AU_REG_IRQGLOB) | AU_IRQ_ENABLE); /* braindead but it's what the oss/linux driver does * for (i=0; i<0x80000000; i++) au_wr(au, 0, i<<2, 0, 4); */ @@ -512,9 +508,9 @@ au_encodec(au, 0); au_encodec(au, 1); - for (i=0; i<48; i++) au_wr(au, 0, 0xf800+(i<<2), 0x20, 4); - for (i=2; i<6; i++) au_wr(au, 0, 0xf800+(i<<2), 0, 4); - au_wr(au, 0, 0xf8c0, 0x0843, 4); + for (i=0; i<48; i++) au_wr4(au, 0xf800+(i<<2), 0x20); + for (i=2; i<6; i++) au_wr4(au, 0xf800+(i<<2), 0); + au_wr4(au, 0xf8c0, 0x0843); for (i=0; i<4; i++) au_clrfifo(au, i); return (0); @@ -523,15 +519,27 @@ static int au_testirq(struct au_info *au) { - au_wr(au, 0, AU_REG_UNK1, 0x80001000, 4); - au_wr(au, 0, AU_REG_IRQEN, 0x00001030, 4); - au_wr(au, 0, AU_REG_IRQSRC, 0x000007ff, 4); + au_wr4(au, AU_REG_UNK1, 0x80001000); + au_wr4(au, AU_REG_IRQEN, 0x00001030); + au_wr4(au, AU_REG_IRQSRC, 0x000007ff); DELAY(1000000); if (au->interrupts==0) printf("pcm%d: irq test failed\n", au->unit); /* this apparently generates an irq */ return 0; } +static void +au_destroy(device_t dev, au_info *sc) +{ + if (!sc) + return; + + if (sc->ih) + bus_teardown_intr(dev, sc->res[RES_IRQ], sc->ih); + bus_release_resources(dev, sc->spec, sc->res); + free(sc, M_DEVBUF); +} + static int au_pci_probe(device_t dev) { @@ -546,92 +554,49 @@ static int au_pci_attach(device_t dev) { - u_int32_t data; - struct au_info *au; - int type[10]; - int regid[10]; - struct resource *reg[10]; - int i, j, mapped = 0; - int irqid; - struct resource *irq = 0; - void *ih = 0; + struct au_info *sc; struct ac97_info *codec; char status[SND_STATUSLEN]; - au = malloc(sizeof(*au), M_DEVBUF, M_WAITOK | M_ZERO); - au->unit = device_get_unit(dev); + sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO); + if (sc == NULL) { + device_printf(dev, "cannot allocate softc\n"); + return ENXIO; + } + sc->unit = device_get_unit(dev); - data = pci_read_config(dev, PCIR_COMMAND, 2); - data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN); - pci_write_config(dev, PCIR_COMMAND, data, 2); - data = pci_read_config(dev, PCIR_COMMAND, 2); + pci_enable_busmaster(dev); + pci_enable_io(dev, SYS_RES_IOPORT); + pci_enable_io(dev, SYS_RES_MEMORY); - j=0; - /* XXX dfr: is this strictly necessary? */ - for (i=0; i<PCI_MAXMAPS_0; i++) { -#if 0 - /* Slapped wrist: config_id and map are private structures */ - if (bootverbose) { - printf("pcm%d: map %d - allocating ", unit, i+1); - printf("0x%x bytes of ", 1<<config_id->map[i].ln2size); - printf("%s space ", (config_id->map[i].type & PCI_MAPPORT)? - "io" : "memory"); - printf("at 0x%x...", config_id->map[i].base); + sc->spec = au_res_spec_mem; + if (bus_alloc_resources(dev, sc->spec, sc->res) != 0) { + sc->spec = au_res_spec_io; + if (bus_alloc_resources(dev, sc->spec, sc->res) != 0) { + device_printf(dev, "unable to allocate resources\n"); + goto bad; } -#endif - regid[j] = PCIR_BAR(i); - type[j] = SYS_RES_MEMORY; - reg[j] = bus_alloc_resource_any(dev, type[j], ®id[j], - RF_ACTIVE); - if (!reg[j]) { - type[j] = SYS_RES_IOPORT; - reg[j] = bus_alloc_resource_any(dev, type[j], - ®id[j], RF_ACTIVE); - } - if (reg[j]) { - au->st[i] = rman_get_bustag(reg[j]); - au->sh[i] = rman_get_bushandle(reg[j]); - mapped++; - } -#if 0 - if (bootverbose) printf("%s\n", mapped? "ok" : "failed"); -#endif - if (mapped) j++; - if (j == 10) { - /* XXX */ - device_printf(dev, "too many resources"); - goto bad; - } - } + } -#if 0 - if (j < config_id->nummaps) { - printf("pcm%d: unable to map a required resource\n", unit); - free(au, M_DEVBUF); - return; - } -#endif - - au_wr(au, 0, AU_REG_IRQEN, 0, 4); - - irqid = 0; - irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &irqid, - RF_ACTIVE | RF_SHAREABLE); - if (!irq || snd_setup_intr(dev, irq, 0, au_intr, au, &ih)) { + au_wr4(sc, AU_REG_IRQEN, 0); + if (snd_setup_intr(dev, sc->res[RES_IRQ], 0, au_intr, sc, &sc->ih)) { device_printf(dev, "unable to map interrupt\n"); goto bad; } - if (au_testirq(au)) device_printf(dev, "irq test failed\n"); + if (au_testirq(sc)) + device_printf(dev, "irq test failed\n"); - if (au_init(dev, au) == -1) { + if (au_init(dev, sc) == -1) { device_printf(dev, "unable to initialize the card\n"); goto bad; } - codec = AC97_CREATE(dev, au, au_ac97); - if (codec == NULL) goto bad; - if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto bad; + codec = AC97_CREATE(dev, sc, au_ac97); + if (codec == NULL) + goto bad; + if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) + goto bad; if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2, /*boundary*/0, @@ -646,29 +611,47 @@ } snprintf(status, SND_STATUSLEN, "at %s 0x%lx irq %ld %s", - (type[0] == SYS_RES_IOPORT)? "io" : "memory", - rman_get_start(reg[0]), rman_get_start(irq),PCM_KLDSTRING(snd_aureal)); + (sc->spec == au_res_spec_io)? "io" : "memory", + rman_get_start(sc->res[RES_P0]), + rman_get_start(sc->res[RES_IRQ]), + PCM_KLDSTRING(snd_aureal)); - if (pcm_register(dev, au, 1, 1)) goto bad; + if (pcm_register(dev, sc, 1, 1)) + goto bad; /* pcm_addchan(dev, PCMDIR_REC, &au_chantemplate, au); */ - pcm_addchan(dev, PCMDIR_PLAY, &auchan_class, au); + pcm_addchan(dev, PCMDIR_PLAY, &auchan_class, sc); pcm_setstatus(dev, status); return 0; bad: - if (au) free(au, M_DEVBUF); - for (i = 0; i < j; i++) - bus_release_resource(dev, type[i], regid[i], reg[i]); - if (ih) bus_teardown_intr(dev, irq, ih); - if (irq) bus_release_resource(dev, SYS_RES_IRQ, irqid, irq); + au_destroy(dev, sc); return ENXIO; } +static int +au_pci_detach(device_t dev) +{ + int ret; + struct au_info *sc; + + ret = pcm_unregister(dev); + if (ret) + return ret; + + sc = pcm_getdevinfo(dev); + + /* XXX: how to shut down card?? */ + au_destroy(dev, sc); + + return 0; +} + static device_method_t au_methods[] = { /* Device interface */ DEVMETHOD(device_probe, au_pci_probe), DEVMETHOD(device_attach, au_pci_attach), + DEVMETHOD(device_detach, au_pci_detach), { 0, 0 } };
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200707232339.l6NNd5rh035088>
