xref: /freebsd/sys/dev/sound/pci/neomagic.c (revision 6990ffd8a95caaba6858ad44ff1b3157d1efba8f)
1 /*
2  * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk>
3  * All rights reserved.
4  *
5  * Derived from the public domain Linux driver
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <dev/sound/pcm/sound.h>
30 #include <dev/sound/pcm/ac97.h>
31 #include <dev/sound/pci/neomagic.h>
32 #include <dev/sound/pci/neomagic-coeff.h>
33 
34 #include <pci/pcireg.h>
35 #include <pci/pcivar.h>
36 
37 SND_DECLARE_FILE("$FreeBSD$");
38 
39 /* -------------------------------------------------------------------- */
40 
41 #define	NM_BUFFSIZE	16384
42 
43 #define NM256AV_PCI_ID 	0x800510c8
44 #define NM256ZX_PCI_ID 	0x800610c8
45 
46 struct sc_info;
47 
48 /* channel registers */
49 struct sc_chinfo {
50 	int spd, dir, fmt;
51 	struct snd_dbuf *buffer;
52 	struct pcm_channel *channel;
53 	struct sc_info *parent;
54 };
55 
56 /* device private data */
57 struct sc_info {
58 	device_t	dev;
59 	u_int32_t 	type;
60 
61 	struct resource *reg, *irq, *buf;
62 	int		regid, irqid, bufid;
63 	void		*ih;
64 
65 	u_int32_t 	ac97_base, ac97_status, ac97_busy;
66 	u_int32_t	buftop, pbuf, rbuf, cbuf, acbuf;
67 	u_int32_t	playint, recint, misc1int, misc2int;
68 	u_int32_t	irsz, badintr;
69 
70 	struct sc_chinfo pch, rch;
71 };
72 
73 /* -------------------------------------------------------------------- */
74 
75 /*
76  * prototypes
77  */
78 
79 /* stuff */
80 static int 	 nm_loadcoeff(struct sc_info *sc, int dir, int num);
81 static int	 nm_setch(struct sc_chinfo *ch);
82 static int       nm_init(struct sc_info *);
83 static void      nm_intr(void *);
84 
85 /* talk to the card */
86 static u_int32_t nm_rd(struct sc_info *, int, int);
87 static void 	 nm_wr(struct sc_info *, int, u_int32_t, int);
88 static u_int32_t nm_rdbuf(struct sc_info *, int, int);
89 static void 	 nm_wrbuf(struct sc_info *, int, u_int32_t, int);
90 
91 static u_int32_t badcards[] = {
92 	0x0007103c,
93 	0x008f1028,
94 	0x00dd1014,
95 	0x8005110a,
96 };
97 #define NUM_BADCARDS (sizeof(badcards) / sizeof(u_int32_t))
98 
99 /* The actual rates supported by the card. */
100 static int samplerates[9] = {
101 	8000,
102 	11025,
103 	16000,
104 	22050,
105 	24000,
106 	32000,
107 	44100,
108 	48000,
109 	99999999
110 };
111 
112 /* -------------------------------------------------------------------- */
113 
114 static u_int32_t nm_fmt[] = {
115 	AFMT_U8,
116 	AFMT_STEREO | AFMT_U8,
117 	AFMT_S16_LE,
118 	AFMT_STEREO | AFMT_S16_LE,
119 	0
120 };
121 static struct pcmchan_caps nm_caps = {4000, 48000, nm_fmt, 0};
122 
123 /* -------------------------------------------------------------------- */
124 
125 /* Hardware */
126 static u_int32_t
127 nm_rd(struct sc_info *sc, int regno, int size)
128 {
129 	bus_space_tag_t st = rman_get_bustag(sc->reg);
130 	bus_space_handle_t sh = rman_get_bushandle(sc->reg);
131 
132 	switch (size) {
133 	case 1:
134 		return bus_space_read_1(st, sh, regno);
135 	case 2:
136 		return bus_space_read_2(st, sh, regno);
137 	case 4:
138 		return bus_space_read_4(st, sh, regno);
139 	default:
140 		return 0xffffffff;
141 	}
142 }
143 
144 static void
145 nm_wr(struct sc_info *sc, int regno, u_int32_t data, int size)
146 {
147 	bus_space_tag_t st = rman_get_bustag(sc->reg);
148 	bus_space_handle_t sh = rman_get_bushandle(sc->reg);
149 
150 	switch (size) {
151 	case 1:
152 		bus_space_write_1(st, sh, regno, data);
153 		break;
154 	case 2:
155 		bus_space_write_2(st, sh, regno, data);
156 		break;
157 	case 4:
158 		bus_space_write_4(st, sh, regno, data);
159 		break;
160 	}
161 }
162 
163 static u_int32_t
164 nm_rdbuf(struct sc_info *sc, int regno, int size)
165 {
166 	bus_space_tag_t st = rman_get_bustag(sc->buf);
167 	bus_space_handle_t sh = rman_get_bushandle(sc->buf);
168 
169 	switch (size) {
170 	case 1:
171 		return bus_space_read_1(st, sh, regno);
172 	case 2:
173 		return bus_space_read_2(st, sh, regno);
174 	case 4:
175 		return bus_space_read_4(st, sh, regno);
176 	default:
177 		return 0xffffffff;
178 	}
179 }
180 
181 static void
182 nm_wrbuf(struct sc_info *sc, int regno, u_int32_t data, int size)
183 {
184 	bus_space_tag_t st = rman_get_bustag(sc->buf);
185 	bus_space_handle_t sh = rman_get_bushandle(sc->buf);
186 
187 	switch (size) {
188 	case 1:
189 		bus_space_write_1(st, sh, regno, data);
190 		break;
191 	case 2:
192 		bus_space_write_2(st, sh, regno, data);
193 		break;
194 	case 4:
195 		bus_space_write_4(st, sh, regno, data);
196 		break;
197 	}
198 }
199 
200 /* -------------------------------------------------------------------- */
201 /* ac97 codec */
202 static int
203 nm_waitcd(struct sc_info *sc)
204 {
205 	int cnt = 10;
206 
207 	while (cnt-- > 0) {
208 		if (nm_rd(sc, sc->ac97_status, 2) & sc->ac97_busy)
209 			DELAY(100);
210 		else
211 			break;
212 	}
213 	return (nm_rd(sc, sc->ac97_status, 2) & sc->ac97_busy);
214 }
215 
216 static u_int32_t
217 nm_initcd(kobj_t obj, void *devinfo)
218 {
219 	struct sc_info *sc = (struct sc_info *)devinfo;
220 
221 	nm_wr(sc, 0x6c0, 0x01, 1);
222 	nm_wr(sc, 0x6cc, 0x87, 1);
223 	nm_wr(sc, 0x6cc, 0x80, 1);
224 	nm_wr(sc, 0x6cc, 0x00, 1);
225 	return 1;
226 }
227 
228 static int
229 nm_rdcd(kobj_t obj, void *devinfo, int regno)
230 {
231 	struct sc_info *sc = (struct sc_info *)devinfo;
232 	u_int32_t x;
233 
234 	if (!nm_waitcd(sc)) {
235 		x = nm_rd(sc, sc->ac97_base + regno, 2);
236 		DELAY(1000);
237 		return x;
238 	} else {
239 		device_printf(sc->dev, "ac97 codec not ready\n");
240 		return -1;
241 	}
242 }
243 
244 static int
245 nm_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data)
246 {
247 	struct sc_info *sc = (struct sc_info *)devinfo;
248 	int cnt = 3;
249 
250 	if (!nm_waitcd(sc)) {
251 		while (cnt-- > 0) {
252 			nm_wr(sc, sc->ac97_base + regno, data, 2);
253 			if (!nm_waitcd(sc)) {
254 				DELAY(1000);
255 				return 0;
256 			}
257 		}
258 	}
259 	device_printf(sc->dev, "ac97 codec not ready\n");
260 	return -1;
261 }
262 
263 static kobj_method_t nm_ac97_methods[] = {
264     	KOBJMETHOD(ac97_init,		nm_initcd),
265     	KOBJMETHOD(ac97_read,		nm_rdcd),
266     	KOBJMETHOD(ac97_write,		nm_wrcd),
267 	{ 0, 0 }
268 };
269 AC97_DECLARE(nm_ac97);
270 
271 /* -------------------------------------------------------------------- */
272 
273 static void
274 nm_ackint(struct sc_info *sc, u_int32_t num)
275 {
276 	if (sc->type == NM256AV_PCI_ID) {
277 		nm_wr(sc, NM_INT_REG, num << 1, 2);
278 	} else if (sc->type == NM256ZX_PCI_ID) {
279 		nm_wr(sc, NM_INT_REG, num, 4);
280 	}
281 }
282 
283 static int
284 nm_loadcoeff(struct sc_info *sc, int dir, int num)
285 {
286 	int ofs, sz, i;
287 	u_int32_t addr;
288 
289 	addr = (dir == PCMDIR_PLAY)? 0x01c : 0x21c;
290 	if (dir == PCMDIR_REC)
291 		num += 8;
292 	sz = coefficientSizes[num];
293 	ofs = 0;
294 	while (num-- > 0)
295 		ofs+= coefficientSizes[num];
296 	for (i = 0; i < sz; i++)
297 		nm_wrbuf(sc, sc->cbuf + i, coefficients[ofs + i], 1);
298 	nm_wr(sc, addr, sc->cbuf, 4);
299 	if (dir == PCMDIR_PLAY)
300 		sz--;
301 	nm_wr(sc, addr + 4, sc->cbuf + sz, 4);
302 	return 0;
303 }
304 
305 static int
306 nm_setch(struct sc_chinfo *ch)
307 {
308 	struct sc_info *sc = ch->parent;
309 	u_int32_t base;
310 	u_int8_t x;
311 
312 	for (x = 0; x < 8; x++)
313 		if (ch->spd < (samplerates[x] + samplerates[x + 1]) / 2)
314 			break;
315 
316 	if (x == 8) return 1;
317 
318 	ch->spd = samplerates[x];
319 	nm_loadcoeff(sc, ch->dir, x);
320 
321 	x <<= 4;
322 	x &= NM_RATE_MASK;
323 	if (ch->fmt & AFMT_16BIT) x |= NM_RATE_BITS_16;
324 	if (ch->fmt & AFMT_STEREO) x |= NM_RATE_STEREO;
325 
326 	base = (ch->dir == PCMDIR_PLAY)? NM_PLAYBACK_REG_OFFSET : NM_RECORD_REG_OFFSET;
327 	nm_wr(sc, base + NM_RATE_REG_OFFSET, x, 1);
328 	return 0;
329 }
330 
331 /* channel interface */
332 static void *
333 nmchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
334 {
335 	struct sc_info *sc = devinfo;
336 	struct sc_chinfo *ch;
337 	u_int32_t chnbuf;
338 
339 	chnbuf = (dir == PCMDIR_PLAY)? sc->pbuf : sc->rbuf;
340 	ch = (dir == PCMDIR_PLAY)? &sc->pch : &sc->rch;
341 	ch->buffer = b;
342 	sndbuf_setup(ch->buffer, (u_int8_t *)rman_get_virtual(sc->buf) + chnbuf, NM_BUFFSIZE);
343 	if (bootverbose)
344 		device_printf(sc->dev, "%s buf %p\n", (dir == PCMDIR_PLAY)?
345 			      "play" : "rec", sndbuf_getbuf(ch->buffer));
346 	ch->parent = sc;
347 	ch->channel = c;
348 	ch->dir = dir;
349 	return ch;
350 }
351 
352 static int
353 nmchan_free(kobj_t obj, void *data)
354 {
355 	return 0;
356 }
357 
358 static int
359 nmchan_setformat(kobj_t obj, void *data, u_int32_t format)
360 {
361 	struct sc_chinfo *ch = data;
362 
363 	ch->fmt = format;
364 	return nm_setch(ch);
365 }
366 
367 static int
368 nmchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
369 {
370 	struct sc_chinfo *ch = data;
371 
372 	ch->spd = speed;
373 	return nm_setch(ch)? 0 : ch->spd;
374 }
375 
376 static int
377 nmchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
378 {
379 	return blocksize;
380 }
381 
382 static int
383 nmchan_trigger(kobj_t obj, void *data, int go)
384 {
385 	struct sc_chinfo *ch = data;
386 	struct sc_info *sc = ch->parent;
387 	int ssz;
388 
389 	if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
390 		return 0;
391 
392 	ssz = (ch->fmt & AFMT_16BIT)? 2 : 1;
393 	if (ch->fmt & AFMT_STEREO)
394 		ssz <<= 1;
395 
396 	if (ch->dir == PCMDIR_PLAY) {
397 		if (go == PCMTRIG_START) {
398 			nm_wr(sc, NM_PBUFFER_START, sc->pbuf, 4);
399 			nm_wr(sc, NM_PBUFFER_END, sc->pbuf + NM_BUFFSIZE - ssz, 4);
400 			nm_wr(sc, NM_PBUFFER_CURRP, sc->pbuf, 4);
401 			nm_wr(sc, NM_PBUFFER_WMARK, sc->pbuf + NM_BUFFSIZE / 2, 4);
402 			nm_wr(sc, NM_PLAYBACK_ENABLE_REG, NM_PLAYBACK_FREERUN |
403 				NM_PLAYBACK_ENABLE_FLAG, 1);
404 			nm_wr(sc, NM_AUDIO_MUTE_REG, 0, 2);
405 		} else {
406 			nm_wr(sc, NM_PLAYBACK_ENABLE_REG, 0, 1);
407 			nm_wr(sc, NM_AUDIO_MUTE_REG, NM_AUDIO_MUTE_BOTH, 2);
408 		}
409 	} else {
410 		if (go == PCMTRIG_START) {
411 			nm_wr(sc, NM_RECORD_ENABLE_REG, NM_RECORD_FREERUN |
412 				NM_RECORD_ENABLE_FLAG, 1);
413 			nm_wr(sc, NM_RBUFFER_START, sc->rbuf, 4);
414 			nm_wr(sc, NM_RBUFFER_END, sc->rbuf + NM_BUFFSIZE, 4);
415 			nm_wr(sc, NM_RBUFFER_CURRP, sc->rbuf, 4);
416 			nm_wr(sc, NM_RBUFFER_WMARK, sc->rbuf + NM_BUFFSIZE / 2, 4);
417 		} else {
418 			nm_wr(sc, NM_RECORD_ENABLE_REG, 0, 1);
419 		}
420 	}
421 	return 0;
422 }
423 
424 static int
425 nmchan_getptr(kobj_t obj, void *data)
426 {
427 	struct sc_chinfo *ch = data;
428 	struct sc_info *sc = ch->parent;
429 
430 	if (ch->dir == PCMDIR_PLAY)
431 		return nm_rd(sc, NM_PBUFFER_CURRP, 4) - sc->pbuf;
432 	else
433 		return nm_rd(sc, NM_RBUFFER_CURRP, 4) - sc->rbuf;
434 }
435 
436 static struct pcmchan_caps *
437 nmchan_getcaps(kobj_t obj, void *data)
438 {
439 	return &nm_caps;
440 }
441 
442 static kobj_method_t nmchan_methods[] = {
443     	KOBJMETHOD(channel_init,		nmchan_init),
444     	KOBJMETHOD(channel_free,		nmchan_free),
445     	KOBJMETHOD(channel_setformat,		nmchan_setformat),
446     	KOBJMETHOD(channel_setspeed,		nmchan_setspeed),
447     	KOBJMETHOD(channel_setblocksize,	nmchan_setblocksize),
448     	KOBJMETHOD(channel_trigger,		nmchan_trigger),
449     	KOBJMETHOD(channel_getptr,		nmchan_getptr),
450     	KOBJMETHOD(channel_getcaps,		nmchan_getcaps),
451 	{ 0, 0 }
452 };
453 CHANNEL_DECLARE(nmchan);
454 
455 /* The interrupt handler */
456 static void
457 nm_intr(void *p)
458 {
459 	struct sc_info *sc = (struct sc_info *)p;
460 	int status, x;
461 
462 	status = nm_rd(sc, NM_INT_REG, sc->irsz);
463 	if (status == 0)
464 		return;
465 
466 	if (status & sc->playint) {
467 		status &= ~sc->playint;
468 		nm_ackint(sc, sc->playint);
469 		chn_intr(sc->pch.channel);
470 	}
471 	if (status & sc->recint) {
472 		status &= ~sc->recint;
473 		nm_ackint(sc, sc->recint);
474 		chn_intr(sc->rch.channel);
475 	}
476 	if (status & sc->misc1int) {
477 		status &= ~sc->misc1int;
478 		nm_ackint(sc, sc->misc1int);
479 		x = nm_rd(sc, 0x400, 1);
480 		nm_wr(sc, 0x400, x | 2, 1);
481 	 	device_printf(sc->dev, "misc int 1\n");
482 	}
483 	if (status & sc->misc2int) {
484 		status &= ~sc->misc2int;
485 		nm_ackint(sc, sc->misc2int);
486 		x = nm_rd(sc, 0x400, 1);
487 		nm_wr(sc, 0x400, x & ~2, 1);
488 	 	device_printf(sc->dev, "misc int 2\n");
489 	}
490 	if (status) {
491 		nm_ackint(sc, status);
492 	 	device_printf(sc->dev, "unknown int\n");
493 	}
494 }
495 
496 /* -------------------------------------------------------------------- */
497 
498 /*
499  * Probe and attach the card
500  */
501 
502 static int
503 nm_init(struct sc_info *sc)
504 {
505 	u_int32_t ofs, i;
506 
507 	if (sc->type == NM256AV_PCI_ID) {
508 		sc->ac97_base = NM_MIXER_OFFSET;
509 		sc->ac97_status = NM_MIXER_STATUS_OFFSET;
510 		sc->ac97_busy = NM_MIXER_READY_MASK;
511 
512 		sc->buftop = 2560 * 1024;
513 
514 		sc->irsz = 2;
515 		sc->playint = NM_PLAYBACK_INT;
516 		sc->recint = NM_RECORD_INT;
517 		sc->misc1int = NM_MISC_INT_1;
518 		sc->misc2int = NM_MISC_INT_2;
519 	} else if (sc->type == NM256ZX_PCI_ID) {
520 		sc->ac97_base = NM_MIXER_OFFSET;
521 		sc->ac97_status = NM2_MIXER_STATUS_OFFSET;
522 		sc->ac97_busy = NM2_MIXER_READY_MASK;
523 
524 		sc->buftop = (nm_rd(sc, 0xa0b, 2)? 6144 : 4096) * 1024;
525 
526 		sc->irsz = 4;
527 		sc->playint = NM2_PLAYBACK_INT;
528 		sc->recint = NM2_RECORD_INT;
529 		sc->misc1int = NM2_MISC_INT_1;
530 		sc->misc2int = NM2_MISC_INT_2;
531 	} else return -1;
532 	sc->badintr = 0;
533 	ofs = sc->buftop - 0x0400;
534 	sc->buftop -= 0x1400;
535 
536  	if ((nm_rdbuf(sc, ofs, 4) & NM_SIG_MASK) == NM_SIGNATURE) {
537 		i = nm_rdbuf(sc, ofs + 4, 4);
538 		if (i != 0 && i != 0xffffffff)
539 			sc->buftop = i;
540 	}
541 
542 	sc->cbuf = sc->buftop - NM_MAX_COEFFICIENT;
543 	sc->rbuf = sc->cbuf - NM_BUFFSIZE;
544 	sc->pbuf = sc->rbuf - NM_BUFFSIZE;
545 	sc->acbuf = sc->pbuf - (NM_TOTAL_COEFF_COUNT * 4);
546 
547 	nm_wr(sc, 0, 0x11, 1);
548 	nm_wr(sc, NM_RECORD_ENABLE_REG, 0, 1);
549 	nm_wr(sc, 0x214, 0, 2);
550 
551 	return 0;
552 }
553 
554 static int
555 nm_pci_probe(device_t dev)
556 {
557 	struct sc_info *sc = NULL;
558 	char *s = NULL;
559 	u_int32_t subdev, i, data;
560 
561 	subdev = (pci_get_subdevice(dev) << 16) | pci_get_subvendor(dev);
562 	switch (pci_get_devid(dev)) {
563 	case NM256AV_PCI_ID:
564 		i = 0;
565 		while ((i < NUM_BADCARDS) && (badcards[i] != subdev))
566 			i++;
567 
568 		/* Try to catch other non-ac97 cards */
569 
570 		if (i == NUM_BADCARDS) {
571 			if (!(sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT | M_ZERO))) {
572 				device_printf(dev, "cannot allocate softc\n");
573 				return ENXIO;
574 			}
575 
576 			data = pci_read_config(dev, PCIR_COMMAND, 2);
577 			pci_write_config(dev, PCIR_COMMAND, data |
578 					 PCIM_CMD_PORTEN | PCIM_CMD_MEMEN |
579 					 PCIM_CMD_BUSMASTEREN, 2);
580 
581 			sc->regid = PCIR_MAPS + 4;
582 			sc->reg = bus_alloc_resource(dev, SYS_RES_MEMORY,
583 						     &sc->regid, 0, ~0, 1,
584 						     RF_ACTIVE);
585 
586 			if (!sc->reg) {
587 				device_printf(dev, "unable to map register space\n");
588 				pci_write_config(dev, PCIR_COMMAND, data, 2);
589 				free(sc, M_DEVBUF);
590 				return ENXIO;
591 			}
592 
593 			if ((nm_rd(sc, NM_MIXER_PRESENCE, 2) &
594 				NM_PRESENCE_MASK) != NM_PRESENCE_VALUE) {
595 				i = 0;	/* non-ac97 card, but not listed */
596 				DEB(device_printf(dev, "subdev = 0x%x - badcard?\n",
597 				    subdev));
598 			}
599 			pci_write_config(dev, PCIR_COMMAND, data, 2);
600 			bus_release_resource(dev, SYS_RES_MEMORY, sc->regid,
601 					     sc->reg);
602 			free(sc, M_DEVBUF);
603 		}
604 
605 		if (i == NUM_BADCARDS)
606 			s = "NeoMagic 256AV";
607 		DEB(else)
608 			DEB(device_printf(dev, "this is a non-ac97 NM256AV, not attaching\n"));
609 
610 		break;
611 
612 	case NM256ZX_PCI_ID:
613 		s = "NeoMagic 256ZX";
614 		break;
615 	}
616 
617 	if (s) device_set_desc(dev, s);
618 	return s? 0 : ENXIO;
619 }
620 
621 static int
622 nm_pci_attach(device_t dev)
623 {
624 	u_int32_t	data;
625 	struct sc_info *sc;
626 	struct ac97_info *codec = 0;
627 	char 		status[SND_STATUSLEN];
628 
629 	if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) {
630 		device_printf(dev, "cannot allocate softc\n");
631 		return ENXIO;
632 	}
633 
634 	sc->dev = dev;
635 	sc->type = pci_get_devid(dev);
636 
637 	data = pci_read_config(dev, PCIR_COMMAND, 2);
638 	data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
639 	pci_write_config(dev, PCIR_COMMAND, data, 2);
640 	data = pci_read_config(dev, PCIR_COMMAND, 2);
641 
642 	sc->bufid = PCIR_MAPS;
643 	sc->buf = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->bufid,
644 				     0, ~0, 1, RF_ACTIVE);
645 	sc->regid = PCIR_MAPS + 4;
646 	sc->reg = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->regid,
647 				     0, ~0, 1, RF_ACTIVE);
648 
649 	if (!sc->buf || !sc->reg) {
650 		device_printf(dev, "unable to map register space\n");
651 		goto bad;
652 	}
653 
654 	if (nm_init(sc) == -1) {
655 		device_printf(dev, "unable to initialize the card\n");
656 		goto bad;
657 	}
658 
659 	codec = AC97_CREATE(dev, sc, nm_ac97);
660 	if (codec == NULL) goto bad;
661 	if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto bad;
662 
663 	sc->irqid = 0;
664 	sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irqid,
665 				 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
666 	if (!sc->irq || snd_setup_intr(dev, sc->irq, 0, nm_intr, sc, &sc->ih)) {
667 		device_printf(dev, "unable to map interrupt\n");
668 		goto bad;
669 	}
670 
671 	snprintf(status, SND_STATUSLEN, "at memory 0x%lx, 0x%lx irq %ld",
672 		 rman_get_start(sc->buf), rman_get_start(sc->reg),
673 		 rman_get_start(sc->irq));
674 
675 	if (pcm_register(dev, sc, 1, 1)) goto bad;
676 	pcm_addchan(dev, PCMDIR_REC, &nmchan_class, sc);
677 	pcm_addchan(dev, PCMDIR_PLAY, &nmchan_class, sc);
678 	pcm_setstatus(dev, status);
679 
680 	return 0;
681 
682 bad:
683 	if (codec) ac97_destroy(codec);
684 	if (sc->buf) bus_release_resource(dev, SYS_RES_MEMORY, sc->bufid, sc->buf);
685 	if (sc->reg) bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg);
686 	if (sc->ih) bus_teardown_intr(dev, sc->irq, sc->ih);
687 	if (sc->irq) bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
688 	free(sc, M_DEVBUF);
689 	return ENXIO;
690 }
691 
692 static int
693 nm_pci_detach(device_t dev)
694 {
695 	int r;
696 	struct sc_info *sc;
697 
698 	r = pcm_unregister(dev);
699 	if (r)
700 		return r;
701 
702 	sc = pcm_getdevinfo(dev);
703 	bus_release_resource(dev, SYS_RES_MEMORY, sc->bufid, sc->buf);
704 	bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg);
705 	bus_teardown_intr(dev, sc->irq, sc->ih);
706 	bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
707 	free(sc, M_DEVBUF);
708 
709 	return 0;
710 }
711 
712 static int
713 nm_pci_resume(device_t dev)
714 {
715 	struct sc_info *sc;
716 
717 	sc = pcm_getdevinfo(dev);
718 
719 	/* Reinit audio device */
720     	if (nm_init(sc) == -1) {
721 		device_printf(dev, "unable to reinitialize the card\n");
722 		return ENXIO;
723 	}
724 	/* Reinit mixer */
725     	if (mixer_reinit(dev) == -1) {
726 		device_printf(dev, "unable to reinitialize the mixer\n");
727 		return ENXIO;
728 	}
729 	return 0;
730 }
731 
732 static device_method_t nm_methods[] = {
733 	/* Device interface */
734 	DEVMETHOD(device_probe,		nm_pci_probe),
735 	DEVMETHOD(device_attach,	nm_pci_attach),
736 	DEVMETHOD(device_detach,	nm_pci_detach),
737 	DEVMETHOD(device_resume,	nm_pci_resume),
738 	{ 0, 0 }
739 };
740 
741 static driver_t nm_driver = {
742 	"pcm",
743 	nm_methods,
744 	PCM_SOFTC_SIZE,
745 };
746 
747 DRIVER_MODULE(snd_neomagic, pci, nm_driver, pcm_devclass, 0, 0);
748 MODULE_DEPEND(snd_neomagic, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER);
749 MODULE_VERSION(snd_neomagic, 1);
750