Index: uspace/drv/audio/sb16/dsp.c
===================================================================
--- uspace/drv/audio/sb16/dsp.c	(revision bde691c94fe7d6aed67f175af380707953b611e9)
+++ uspace/drv/audio/sb16/dsp.c	(revision bf38143d17200c06e822b797a8ed8eb1e68b388c)
@@ -34,9 +34,86 @@
 
 #include <libarch/ddi.h>
+#include "ddf_log.h"
+#include "dsp_commands.h"
 #include "dsp.h"
 
-int dsp_play_direct(sb16_regs_t *regs, const uint8_t *data, size_t size,
+
+#ifndef DSP_RETRY_COUNT
+#define DSP_RETRY_COUNT 100
+#endif
+
+#define DSP_RESET_RESPONSE 0xaa
+
+static inline int sb_dsp_read(sb_dsp_t *dsp, uint8_t *data)
+{
+	assert(data);
+	assert(dsp);
+	uint8_t status;
+	size_t attempts = DSP_RETRY_COUNT;
+	do {
+		status = pio_read_8(&dsp->regs->dsp_read_status);
+	} while (--attempts && ((status & DSP_READ_READY) == 0));
+
+	if ((status & DSP_READ_READY) == 0)
+		return EIO;
+
+	*data = pio_read_8(&dsp->regs->dsp_data_read);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+static inline int sb_dsp_write(sb_dsp_t *dsp, uint8_t data)
+{
+	assert(dsp);
+	uint8_t status;
+	size_t attempts = DSP_RETRY_COUNT;
+	do {
+		status = pio_read_8(&dsp->regs->dsp_write);
+	} while (--attempts && ((status & DSP_WRITE_BUSY) != 0));
+
+	if ((status & DSP_WRITE_BUSY))
+		return EIO;
+
+	pio_write_8(&dsp->regs->dsp_write, data);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+static inline void sb_dsp_reset(sb_dsp_t *dsp)
+{
+	assert(dsp);
+	/* Reset DSP, see Chapter 2 of Sound Blaster HW programming guide */
+	pio_write_8(&dsp->regs->dsp_reset, 1);
+	udelay(3); /* Keep reset for 3 us */
+	pio_write_8(&dsp->regs->dsp_reset, 0);
+}
+/*----------------------------------------------------------------------------*/
+int sb_dsp_init(sb_dsp_t *dsp, sb16_regs_t *regs)
+{
+	assert(dsp);
+	dsp->regs = regs;
+	sb_dsp_reset(dsp);
+	/* "DSP takes about 100 microseconds to initialize itself" */
+	udelay(100);
+	uint8_t response;
+	const int ret = sb_dsp_read(dsp, &response);
+	if (ret != EOK) {
+		ddf_log_error("Failed to read DSP reset response value.\n");
+		return ret;
+	}
+	if (response != DSP_RESET_RESPONSE) {
+		ddf_log_error("Invalid DSP reset response: %x.\n", response);
+		return EIO;
+	}
+
+	/* Get DSP version number */
+	sb_dsp_write(dsp, DSP_VERSION);
+	sb_dsp_read(dsp, &dsp->version.major);
+	sb_dsp_read(dsp, &dsp->version.minor);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+int sb_dsp_play_direct(sb_dsp_t *dsp, const uint8_t *data, size_t size,
     unsigned sampling_rate, unsigned channels, unsigned bit_depth)
 {
+	assert(dsp);
 	if (channels != 1 || bit_depth != 8)
 		return EIO;
@@ -44,6 +121,6 @@
 	const unsigned wait_period = 1000000 / sampling_rate;
 	while (size--) {
-		pio_write_8(&regs->dsp_write, DIRECT_8B_OUTPUT);
-		pio_write_8(&regs->dsp_write, *data++);
+		pio_write_8(&dsp->regs->dsp_write, DIRECT_8B_OUTPUT);
+		pio_write_8(&dsp->regs->dsp_write, *data++);
 		udelay(wait_period);
 	}
Index: uspace/drv/audio/sb16/dsp.h
===================================================================
--- uspace/drv/audio/sb16/dsp.h	(revision bde691c94fe7d6aed67f175af380707953b611e9)
+++ uspace/drv/audio/sb16/dsp.h	(revision bf38143d17200c06e822b797a8ed8eb1e68b388c)
@@ -39,58 +39,22 @@
 
 #include "registers.h"
-#include "dsp_commands.h"
 
-#ifndef DSP_PIO_DELAY
-#define DSP_PIO_DELAY udelay(10)
-#endif
+typedef struct sb_dsp_t {
+	sb16_regs_t *regs;
+	struct {
+		uint8_t major;
+		uint8_t minor;
+	} version;
+	uint8_t *data_buffer;
+	uint8_t *buffer_position;
+	size_t buffer_size;
+} sb_dsp_t;
 
-#ifndef DSP_RETRY_COUNT
-#define DSP_RETRY_COUNT 100
-#endif
 
-#define DSP_RESET_RESPONSE 0xaa
 
-static inline int dsp_write(sb16_regs_t *regs, uint8_t data)
-{
-	uint8_t status;
-	size_t attempts = DSP_RETRY_COUNT;
-	do {
-		DSP_PIO_DELAY;
-		status = pio_read_8(&regs->dsp_write);
-	} while (--attempts && ((status & DSP_WRITE_BUSY) != 0));
-	if ((status & DSP_WRITE_BUSY))
-		return EIO;
-	DSP_PIO_DELAY;
-	pio_write_8(&regs->dsp_write, data);
-	return EOK;
-}
 /*----------------------------------------------------------------------------*/
-static inline int dsp_read(sb16_regs_t *regs, uint8_t *data)
-{
-	assert(data);
-	uint8_t status;
-	size_t attempts = DSP_RETRY_COUNT;
-	do {
-		DSP_PIO_DELAY;
-		status = pio_read_8(&regs->dsp_read_status);
-	} while (--attempts && ((status & DSP_READ_READY) == 0));
-
-	if ((status & DSP_READ_READY) == 0)
-		return EIO;
-
-	DSP_PIO_DELAY;
-	*data = pio_read_8(&regs->dsp_data_read);
-	return EOK;
-}
+int sb_dsp_init(sb_dsp_t *dsp, sb16_regs_t *regs);
 /*----------------------------------------------------------------------------*/
-static inline void dsp_reset(sb16_regs_t *regs)
-{
-	/* Reset DSP, see Chapter 2 of Sound Blaster HW programming guide */
-	pio_write_8(&regs->dsp_reset, 1);
-	udelay(3); /* Keep reset for 3 us */
-	pio_write_8(&regs->dsp_reset, 0);
-}
-/*----------------------------------------------------------------------------*/
-int dsp_play_direct(sb16_regs_t *regs, const uint8_t *data, size_t size,
+int sb_dsp_play_direct(sb_dsp_t *dsp, const uint8_t *data, size_t size,
     unsigned sample_rate, unsigned channels, unsigned bit_depth);
 #endif
Index: uspace/drv/audio/sb16/sb16.c
===================================================================
--- uspace/drv/audio/sb16/sb16.c	(revision bde691c94fe7d6aed67f175af380707953b611e9)
+++ uspace/drv/audio/sb16/sb16.c	(revision bf38143d17200c06e822b797a8ed8eb1e68b388c)
@@ -68,30 +68,17 @@
 	ddf_log_debug("PIO registers at %p accessible.\n", drv->regs);
 
-	dsp_reset(drv->regs);
-	/* "DSP takes about 100 microseconds to initialize itself" */
-	udelay(100);
-
-	uint8_t response;
-	ret = dsp_read(drv->regs, &response);
+	/* Initialize DSP */
+	ret = sb_dsp_init(&drv->dsp, drv->regs);
 	if (ret != EOK) {
-		ddf_log_error("Failed to read DSP reset response value.\n");
+		ddf_log_error("Failed to initialize SB DSP: %s.\n",
+		    str_error(ret));
 		return ret;
 	}
-
-	if (response != DSP_RESET_RESPONSE) {
-		ddf_log_error("Invalid DSP reset response: %x.\n", response);
-		return EIO;
-	}
-
-	/* Get DSP version number */
-	dsp_write(drv->regs, DSP_VERSION);
-	dsp_read(drv->regs, &drv->dsp_version.major);
-	dsp_read(drv->regs, &drv->dsp_version.minor);
 	ddf_log_note("Sound blaster DSP (%x.%x) initialized.\n",
-	    drv->dsp_version.major, drv->dsp_version.minor);
+	    drv->dsp.version.major, drv->dsp.version.minor);
 
 	/* Initialize mixer */
 	const sb_mixer_type_t mixer_type = sb_mixer_type_by_dsp_version(
-	    drv->dsp_version.major, drv->dsp_version.minor);
+	    drv->dsp.version.major, drv->dsp.version.minor);
 
 	ret = sb_mixer_init(&drv->mixer, drv->regs, mixer_type);
Index: uspace/drv/audio/sb16/sb16.h
===================================================================
--- uspace/drv/audio/sb16/sb16.h	(revision bde691c94fe7d6aed67f175af380707953b611e9)
+++ uspace/drv/audio/sb16/sb16.h	(revision bf38143d17200c06e822b797a8ed8eb1e68b388c)
@@ -39,4 +39,5 @@
 #include <ddi.h>
 
+#include "dsp.h"
 #include "mixer.h"
 #include "registers.h"
@@ -45,8 +46,5 @@
 	sb16_regs_t *regs;
 	mpu_regs_t *mpu_regs;
-	struct {
-		uint8_t major;
-		uint8_t minor;
-	} dsp_version;
+	sb_dsp_t dsp;
 	sb_mixer_t mixer;
 } sb16_drv_t;
