DF-4115 / hblkcnt_max.c
/* * DF-4115/4116 โ drive hblkcnt ABOVE HDA_BDL_MAX and verify the hdaa * clamp is the operative bound on the BDL walk. * * chn_resizebuf (channel.c:1832) computes the hardware request as * hblkcnt = round_pow2(previous soft blkcnt) * so: SETFRAGMENT #1 sets soft blkcnt = 8192 (frag 0x7fff0000); * SETFRAGMENT #2 then hands hdaa hblkcnt=8192 (post-shrink 512 @ blksz 128) * โ hdaa_channel_setfragments must clamp to HDA_BDL_MAX=256. * Then start the stream (write) โ the BDL walk runs with blkcnt=256 max. * Watch dmesg (hw.snd.verbose=4): expect b[32768/128/256]. */ #include <stdio.h> #include <stdint.h> #include <string.h> #include <errno.h> #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.h> #include <sys/soundcard.h> int main(void) { setvbuf(stdout, NULL, _IONBF, 0); char junk[65536]; memset(junk, 0x41, sizeof(junk)); int fd = open("/dev/dsp0", O_WRONLY); if (fd < 0) { printf("[-] open: %s\n", strerror(errno)); return 2; } int fmt = AFMT_S16_LE, ch = 2, sp = 48000; audio_buf_info oi; (void)ioctl(fd, SNDCTL_DSP_SETFMT, &fmt); (void)ioctl(fd, SNDCTL_DSP_CHANNELS, &ch); (void)ioctl(fd, SNDCTL_DSP_SPEED, &sp); int f1 = 0x7fff0000; /* soft blkcnt := 8192 */ (void)ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &f1); memset(&oi, 0, sizeof(oi)); (void)ioctl(fd, SNDCTL_DSP_GETOSPACE, &oi); printf("[1] frag %#x -> soft %d/%d/%d (soft blkcnt now 8192)\n", f1, oi.fragsize, oi.fragstotal, oi.bytes); int f2 = 0x00020001; /* forces hblkcnt=round_pow2(8192) */ (void)ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &f2); memset(&oi, 0, sizeof(oi)); (void)ioctl(fd, SNDCTL_DSP_GETOSPACE, &oi); printf("[2] frag %#x -> soft %d/%d/%d (hw request blkcnt=8192->512)\n", f2, oi.fragsize, oi.fragstotal, oi.bytes); /* Start the stream: hdac_stream_start BDL walk with final blkcnt */ ssize_t n = write(fd, junk, sizeof(junk)); printf("[3] wrote %zd bytes โ stream started; BDL walk ran\n", n); count_info ci; (void)ioctl(fd, SNDCTL_DSP_GETOPTR, &ci); printf("[4] getptr ok bytes=%d\n", ci.bytes); close(fd); printf("[+] double-fragment hblkcnt>256 trigger done, guest alive\n"); return 0; } |