cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pvrusb2-debugifc.c (7702B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 *
      4 *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
      5 */
      6
      7#include <linux/string.h>
      8#include "pvrusb2-debugifc.h"
      9#include "pvrusb2-hdw.h"
     10#include "pvrusb2-debug.h"
     11
     12struct debugifc_mask_item {
     13	const char *name;
     14	unsigned long msk;
     15};
     16
     17
     18static unsigned int debugifc_count_whitespace(const char *buf,
     19					      unsigned int count)
     20{
     21	unsigned int scnt;
     22	char ch;
     23
     24	for (scnt = 0; scnt < count; scnt++) {
     25		ch = buf[scnt];
     26		if (ch == ' ') continue;
     27		if (ch == '\t') continue;
     28		if (ch == '\n') continue;
     29		break;
     30	}
     31	return scnt;
     32}
     33
     34
     35static unsigned int debugifc_count_nonwhitespace(const char *buf,
     36						 unsigned int count)
     37{
     38	unsigned int scnt;
     39	char ch;
     40
     41	for (scnt = 0; scnt < count; scnt++) {
     42		ch = buf[scnt];
     43		if (ch == ' ') break;
     44		if (ch == '\t') break;
     45		if (ch == '\n') break;
     46	}
     47	return scnt;
     48}
     49
     50
     51static unsigned int debugifc_isolate_word(const char *buf,unsigned int count,
     52					  const char **wstrPtr,
     53					  unsigned int *wlenPtr)
     54{
     55	const char *wptr;
     56	unsigned int consume_cnt = 0;
     57	unsigned int wlen;
     58	unsigned int scnt;
     59
     60	wptr = NULL;
     61	wlen = 0;
     62	scnt = debugifc_count_whitespace(buf,count);
     63	consume_cnt += scnt; count -= scnt; buf += scnt;
     64	if (!count) goto done;
     65
     66	scnt = debugifc_count_nonwhitespace(buf,count);
     67	if (!scnt) goto done;
     68	wptr = buf;
     69	wlen = scnt;
     70	consume_cnt += scnt; count -= scnt; buf += scnt;
     71
     72 done:
     73	*wstrPtr = wptr;
     74	*wlenPtr = wlen;
     75	return consume_cnt;
     76}
     77
     78
     79static int debugifc_parse_unsigned_number(const char *buf,unsigned int count,
     80					  u32 *num_ptr)
     81{
     82	u32 result = 0;
     83	int radix = 10;
     84	if ((count >= 2) && (buf[0] == '0') &&
     85	    ((buf[1] == 'x') || (buf[1] == 'X'))) {
     86		radix = 16;
     87		count -= 2;
     88		buf += 2;
     89	} else if ((count >= 1) && (buf[0] == '0')) {
     90		radix = 8;
     91	}
     92
     93	while (count--) {
     94		int val = hex_to_bin(*buf++);
     95		if (val < 0 || val >= radix)
     96			return -EINVAL;
     97		result *= radix;
     98		result += val;
     99	}
    100	*num_ptr = result;
    101	return 0;
    102}
    103
    104
    105static int debugifc_match_keyword(const char *buf,unsigned int count,
    106				  const char *keyword)
    107{
    108	unsigned int kl;
    109	if (!keyword) return 0;
    110	kl = strlen(keyword);
    111	if (kl != count) return 0;
    112	return !memcmp(buf,keyword,kl);
    113}
    114
    115
    116int pvr2_debugifc_print_info(struct pvr2_hdw *hdw,char *buf,unsigned int acnt)
    117{
    118	int bcnt = 0;
    119	int ccnt;
    120	ccnt = scnprintf(buf, acnt, "Driver hardware description: %s\n",
    121			 pvr2_hdw_get_desc(hdw));
    122	bcnt += ccnt; acnt -= ccnt; buf += ccnt;
    123	ccnt = scnprintf(buf,acnt,"Driver state info:\n");
    124	bcnt += ccnt; acnt -= ccnt; buf += ccnt;
    125	ccnt = pvr2_hdw_state_report(hdw,buf,acnt);
    126	bcnt += ccnt; acnt -= ccnt; buf += ccnt;
    127
    128	return bcnt;
    129}
    130
    131
    132int pvr2_debugifc_print_status(struct pvr2_hdw *hdw,
    133			       char *buf,unsigned int acnt)
    134{
    135	int bcnt = 0;
    136	int ccnt;
    137	int ret;
    138	u32 gpio_dir,gpio_in,gpio_out;
    139	struct pvr2_stream_stats stats;
    140	struct pvr2_stream *sp;
    141
    142	ret = pvr2_hdw_is_hsm(hdw);
    143	ccnt = scnprintf(buf,acnt,"USB link speed: %s\n",
    144			 (ret < 0 ? "FAIL" : (ret ? "high" : "full")));
    145	bcnt += ccnt; acnt -= ccnt; buf += ccnt;
    146
    147	gpio_dir = 0; gpio_in = 0; gpio_out = 0;
    148	pvr2_hdw_gpio_get_dir(hdw,&gpio_dir);
    149	pvr2_hdw_gpio_get_out(hdw,&gpio_out);
    150	pvr2_hdw_gpio_get_in(hdw,&gpio_in);
    151	ccnt = scnprintf(buf,acnt,"GPIO state: dir=0x%x in=0x%x out=0x%x\n",
    152			 gpio_dir,gpio_in,gpio_out);
    153	bcnt += ccnt; acnt -= ccnt; buf += ccnt;
    154
    155	ccnt = scnprintf(buf,acnt,"Streaming is %s\n",
    156			 pvr2_hdw_get_streaming(hdw) ? "on" : "off");
    157	bcnt += ccnt; acnt -= ccnt; buf += ccnt;
    158
    159
    160	sp = pvr2_hdw_get_video_stream(hdw);
    161	if (sp) {
    162		pvr2_stream_get_stats(sp, &stats, 0);
    163		ccnt = scnprintf(
    164			buf,acnt,
    165			"Bytes streamed=%u URBs: queued=%u idle=%u ready=%u processed=%u failed=%u\n",
    166			stats.bytes_processed,
    167			stats.buffers_in_queue,
    168			stats.buffers_in_idle,
    169			stats.buffers_in_ready,
    170			stats.buffers_processed,
    171			stats.buffers_failed);
    172		bcnt += ccnt; acnt -= ccnt; buf += ccnt;
    173	}
    174
    175	return bcnt;
    176}
    177
    178
    179static int pvr2_debugifc_do1cmd(struct pvr2_hdw *hdw,const char *buf,
    180				unsigned int count)
    181{
    182	const char *wptr;
    183	unsigned int wlen;
    184	unsigned int scnt;
    185
    186	scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
    187	if (!scnt) return 0;
    188	count -= scnt; buf += scnt;
    189	if (!wptr) return 0;
    190
    191	pvr2_trace(PVR2_TRACE_DEBUGIFC,"debugifc cmd: \"%.*s\"",wlen,wptr);
    192	if (debugifc_match_keyword(wptr,wlen,"reset")) {
    193		scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
    194		if (!scnt) return -EINVAL;
    195		count -= scnt; buf += scnt;
    196		if (!wptr) return -EINVAL;
    197		if (debugifc_match_keyword(wptr,wlen,"cpu")) {
    198			pvr2_hdw_cpureset_assert(hdw,!0);
    199			pvr2_hdw_cpureset_assert(hdw,0);
    200			return 0;
    201		} else if (debugifc_match_keyword(wptr,wlen,"bus")) {
    202			pvr2_hdw_device_reset(hdw);
    203		} else if (debugifc_match_keyword(wptr,wlen,"soft")) {
    204			return pvr2_hdw_cmd_powerup(hdw);
    205		} else if (debugifc_match_keyword(wptr,wlen,"deep")) {
    206			return pvr2_hdw_cmd_deep_reset(hdw);
    207		} else if (debugifc_match_keyword(wptr,wlen,"firmware")) {
    208			return pvr2_upload_firmware2(hdw);
    209		} else if (debugifc_match_keyword(wptr,wlen,"decoder")) {
    210			return pvr2_hdw_cmd_decoder_reset(hdw);
    211		} else if (debugifc_match_keyword(wptr,wlen,"worker")) {
    212			return pvr2_hdw_untrip(hdw);
    213		} else if (debugifc_match_keyword(wptr,wlen,"usbstats")) {
    214			pvr2_stream_get_stats(pvr2_hdw_get_video_stream(hdw),
    215					      NULL, !0);
    216			return 0;
    217		}
    218		return -EINVAL;
    219	} else if (debugifc_match_keyword(wptr,wlen,"cpufw")) {
    220		scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
    221		if (!scnt) return -EINVAL;
    222		count -= scnt; buf += scnt;
    223		if (!wptr) return -EINVAL;
    224		if (debugifc_match_keyword(wptr,wlen,"fetch")) {
    225			scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
    226			if (scnt && wptr) {
    227				count -= scnt; buf += scnt;
    228				if (debugifc_match_keyword(wptr, wlen,
    229							   "prom")) {
    230					pvr2_hdw_cpufw_set_enabled(hdw, 2, !0);
    231				} else if (debugifc_match_keyword(wptr, wlen,
    232								  "ram8k")) {
    233					pvr2_hdw_cpufw_set_enabled(hdw, 0, !0);
    234				} else if (debugifc_match_keyword(wptr, wlen,
    235								  "ram16k")) {
    236					pvr2_hdw_cpufw_set_enabled(hdw, 1, !0);
    237				} else {
    238					return -EINVAL;
    239				}
    240			}
    241			pvr2_hdw_cpufw_set_enabled(hdw,0,!0);
    242			return 0;
    243		} else if (debugifc_match_keyword(wptr,wlen,"done")) {
    244			pvr2_hdw_cpufw_set_enabled(hdw,0,0);
    245			return 0;
    246		} else {
    247			return -EINVAL;
    248		}
    249	} else if (debugifc_match_keyword(wptr,wlen,"gpio")) {
    250		int dir_fl = 0;
    251		int ret;
    252		u32 msk,val;
    253		scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
    254		if (!scnt) return -EINVAL;
    255		count -= scnt; buf += scnt;
    256		if (!wptr) return -EINVAL;
    257		if (debugifc_match_keyword(wptr,wlen,"dir")) {
    258			dir_fl = !0;
    259		} else if (!debugifc_match_keyword(wptr,wlen,"out")) {
    260			return -EINVAL;
    261		}
    262		scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
    263		if (!scnt) return -EINVAL;
    264		count -= scnt; buf += scnt;
    265		if (!wptr) return -EINVAL;
    266		ret = debugifc_parse_unsigned_number(wptr,wlen,&msk);
    267		if (ret) return ret;
    268		scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
    269		if (wptr) {
    270			ret = debugifc_parse_unsigned_number(wptr,wlen,&val);
    271			if (ret) return ret;
    272		} else {
    273			val = msk;
    274			msk = 0xffffffff;
    275		}
    276		if (dir_fl) {
    277			ret = pvr2_hdw_gpio_chg_dir(hdw,msk,val);
    278		} else {
    279			ret = pvr2_hdw_gpio_chg_out(hdw,msk,val);
    280		}
    281		return ret;
    282	}
    283	pvr2_trace(PVR2_TRACE_DEBUGIFC,
    284		   "debugifc failed to recognize cmd: \"%.*s\"",wlen,wptr);
    285	return -EINVAL;
    286}
    287
    288
    289int pvr2_debugifc_docmd(struct pvr2_hdw *hdw,const char *buf,
    290			unsigned int count)
    291{
    292	unsigned int bcnt = 0;
    293	int ret;
    294
    295	while (count) {
    296		for (bcnt = 0; bcnt < count; bcnt++) {
    297			if (buf[bcnt] == '\n') break;
    298		}
    299
    300		ret = pvr2_debugifc_do1cmd(hdw,buf,bcnt);
    301		if (ret < 0) return ret;
    302		if (bcnt < count) bcnt++;
    303		buf += bcnt;
    304		count -= bcnt;
    305	}
    306
    307	return 0;
    308}