Cleanup and add meaningful error reporting

This commit is contained in:
Tony Kuker 2022-01-21 02:37:48 +00:00
parent 9186ef063e
commit 0fcded84d0
2 changed files with 77 additions and 243 deletions

View File

@ -32,11 +32,6 @@
#include "log.h"
#include "controllers/scsidev_ctrl.h"
static unsigned char reverse_table[256];
// #define DUMP_COLOR_PALETTE
// #define DUMP_FRAME_BUFFER
const BYTE SCSIPowerView::m_inquiry_response[] = {
0x03, 0x00, 0x01, 0x01, 0x46, 0x00, 0x00, 0x00, 0x52, 0x41, 0x44, 0x49, 0x55, 0x53, 0x20, 0x20,
0x50, 0x6F, 0x77, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
@ -53,9 +48,6 @@ SCSIPowerView::SCSIPowerView() : Disk("SCPV")
AddCommand(SCSIDEV::eCmdPvWriteColorPalette, "Unknown PowerViewCB", &SCSIPowerView::CmdWriteColorPalette);
AddCommand(SCSIDEV::eCmdUnknownPowerViewCC, "Unknown PowerViewCC", &SCSIPowerView::UnknownCommandCC);
// struct fb_var_screeninfo fbinfo;
// struct fb_fix_screeninfo fbfixinfo;
// create lookup table
for (int i = 0; i < 256; i++) {
unsigned char b = i;
@ -65,43 +57,6 @@ SCSIPowerView::SCSIPowerView() : Disk("SCPV")
reverse_table[i] = b;
}
for(int i=0; i < (256/8); i++){
LOGINFO("%02X %02X %02X %02X %02X %02X %02X %02X ", reverse_table[(i*8)],reverse_table[(i*8)+1],reverse_table[(i*8)+2],reverse_table[(i*8)+3], reverse_table[(i*8)+4], reverse_table[(i*8)+5], reverse_table[(i*8)+6], reverse_table[(i*7)] );
}
// TODO: receive these through a SCSI message sent by the remote
this->screen_width_px = 624;
this->screen_height_px = 840;
this->fbfd = open("/dev/fb0", O_RDWR);
if (this->fbfd == -1)
err(1, "open /dev/fb0");
if (ioctl(this->fbfd, FBIOGET_VSCREENINFO, &fbinfo))
err(1, "ioctl FBIOGET_VSCREENINFO");
if (ioctl(this->fbfd, FBIOGET_FSCREENINFO, &fbfixinfo))
err(1, "ioctl FBIOGET_FSCREENINFO");
// if (fbinfo.bits_per_pixel != 32)
// errx(1, "TODO: support %d bpp", fbinfo.bits_per_pixel);
this->fbwidth = fbinfo.xres;
this->fbheight = fbinfo.yres;
this->fbbpp = fbinfo.bits_per_pixel;
this->fblinelen = fbfixinfo.line_length;
this->fbsize = fbfixinfo.smem_len;
LOGINFO("SCSIVideo drawing on %dx%d %d bpp framebuffer\n",
this->fbwidth, this->fbheight, this->fbbpp);
this->fb = (char *)mmap(0, this->fbsize, PROT_READ | PROT_WRITE, MAP_SHARED,
this->fbfd, 0);
if ((int)this->fb == -1)
err(1, "mmap");
memset(this->fb, 0, this->fbsize);
framebuffer_black = 0;
framebuffer_blue = (/*red*/ 0 << fbinfo.red.offset) |
@ -118,21 +73,16 @@ SCSIPowerView::SCSIPowerView() : Disk("SCPV")
(/*alpha*/ 0 << fbinfo.transp.offset);
this->m_powerview_resolution_x = 624;
this->m_powerview_resolution_y = 840;
fbcon_cursor(false);
fbcon_blank(false);
ClearFrameBuffer(framebuffer_blue);
// Default to one bit color (black & white) if we don't know any better
color_depth = eColorsBW;
color_depth = eColorsNone;
LOGINFO("offsets - r:%d g:%d b:%d a:%d", fbinfo.red.offset, fbinfo.green.offset, fbinfo.blue.offset, fbinfo.transp.offset);
}
//---------------------------------------------------------------------------
//
// Log a message to the framebuffer display
//
//---------------------------------------------------------------------------
void SCSIPowerView::fbcon_text(char* message)
{
int fd = open("/dev/tty1", O_RDWR);
@ -188,7 +138,7 @@ SCSIPowerView::~SCSIPowerView()
// Re-enable the cursor
fbcon_cursor(true);
munmap(this->fb, this->fbsize);
munmap(this->fb, fbfixinfo.smem_len);
close(this->fbfd);
for (auto const& command : commands) {
@ -211,39 +161,20 @@ void SCSIPowerView::ClearFrameBuffer(DWORD blank_color){
// For each column
for (DWORD idx_col_x = 0; idx_col_x < 1024; idx_col_x++){
// int loc = (col * (this->fbbpp / 8)) + (row * this->fblinelen);
uint32_t loc = ((idx_col_x) * (this->fbbpp / 8)) + ((idx_row_y) * fblinelen);
// LOGDEBUG("!!! x:%d y:%d !! pix_idx:%06X pix_byte:%04X pix_bit:%02X pixel: %02X, loc:%08X",idx_col_x, idx_row_y, pixel_byte_idx, pixel_byte, pixel_bit_number, pixel, loc);
*(this->fb + loc + 0) = (blank_color & 0xFF);
*(this->fb + loc + 1) = (blank_color >> 8) & 0xFF;
// TODO: This should dynamically set the framebuffer memory, based upon the
// color depth.
*(this->fb + loc + 2) = (blank_color >> 16) & 0xFF;
// for(int i=0 ; i< (this->fbbpp/8); i++){
// *(this->fb + loc + i) = 0xFF;
// }
}
}
}
void SCSIPowerView::dump_command(SASIDEV *controller){
LOGWARN(" %02X %02X %02X %02X %02X %02X %02X %02X [%02X] \n",
ctrl->cmd[0],
ctrl->cmd[1],
ctrl->cmd[2],
ctrl->cmd[3],
ctrl->cmd[4],
ctrl->cmd[5],
ctrl->cmd[6],
ctrl->cmd[7],
ctrl->cmd[8]);
}
//---------------------------------------------------------------------------
//
// PowerView Read Configuration Parameter
@ -256,7 +187,6 @@ void SCSIPowerView::CmdReadConfig(SASIDEV *controller)
// Set transfer amount
ctrl->length = ctrl->cmd[6];
LOGWARN("%s Message Length %d", __PRETTY_FUNCTION__, (int)ctrl->length);
dump_command(controller);
if (ctrl->length <= 0) {
// Failure (Error)
@ -301,10 +231,9 @@ void SCSIPowerView::CmdReadConfig(SASIDEV *controller)
//---------------------------------------------------------------------------
//
// Unknown Command C9
// Unknown Command C9 - Write a configuration value?
//
//---------------------------------------------------------------------------
// void SCSIPowerView::CmdPvWriteConfig(SASIDEV *controller)
void SCSIPowerView::CmdWriteConfig(SASIDEV *controller)
{
@ -312,7 +241,6 @@ void SCSIPowerView::CmdWriteConfig(SASIDEV *controller)
ctrl->length = ctrl->cmd[6];
LOGTRACE("%s Message Length %d", __PRETTY_FUNCTION__, (int)ctrl->length);
if (ctrl->length == 0){
controller->Status();
}
@ -330,7 +258,7 @@ void SCSIPowerView::CmdWriteConfig(SASIDEV *controller)
//---------------------------------------------------------------------------
//
// Unknown Command CA
// Command to Write a Frame Buffer update
//
//---------------------------------------------------------------------------
void SCSIPowerView::CmdWriteFramebuffer(SASIDEV *controller)
@ -347,28 +275,8 @@ void SCSIPowerView::CmdWriteFramebuffer(SASIDEV *controller)
uint16_t height_y = ctrl->cmd[7] + (ctrl->cmd[6] << 8);
ctrl->length = width_x * height_y;
// if(ctrl->cmd[9] == 0){
// ctrl->length = 0x9600;
// }
// else {
// ctrl->length = ctrl->cmd[7] * 2;
// }
LOGTRACE("%s Message Length %d [%08X]", __PRETTY_FUNCTION__, (int)ctrl->length, (unsigned int)ctrl->length);
// LOGDEBUG(" %02X%02X%02X%02X %02X%02X%02X%02X %02X%02X%02X [%02X %02X]\n",
// ctrl->cmd[0],
// ctrl->cmd[1],
// ctrl->cmd[2],
// ctrl->cmd[3],
// ctrl->cmd[4],
// ctrl->cmd[5],
// ctrl->cmd[6],
// ctrl->cmd[7],
// ctrl->cmd[8],
// ctrl->cmd[9],
// ctrl->cmd[10],
// ctrl->cmd[11],
// ctrl->cmd[12]);
LOGTRACE("%s Message Length %d [%08X]", __PRETTY_FUNCTION__, (int)ctrl->length, (unsigned int)ctrl->length);
if (ctrl->length <= 0) {
// Failure (Error)
@ -386,7 +294,7 @@ void SCSIPowerView::CmdWriteFramebuffer(SASIDEV *controller)
//---------------------------------------------------------------------------
//
// Unknown Command CB
// Receive a new color palette from the host
//
//---------------------------------------------------------------------------
void SCSIPowerView::CmdWriteColorPalette(SASIDEV *controller)
@ -423,12 +331,9 @@ void SCSIPowerView::CmdWriteColorPalette(SASIDEV *controller)
//---------------------------------------------------------------------------
void SCSIPowerView::UnknownCommandCC(SASIDEV *controller)
{
// Set transfer amount
// ctrl->length = ctrl->cmd[6];
ctrl->length = 0x8bb;
LOGTRACE("%s Message Length %d", __PRETTY_FUNCTION__, (int)ctrl->length);
// dump_command(controller);
if (ctrl->length <= 0) {
// Failure (Error)
controller->Error();
@ -466,14 +371,58 @@ bool SCSIPowerView::Init(const map<string, string>& params)
{
SetParams(params.empty() ? GetDefaultParams() : params);
this->fbfd = open("/dev/fb0", O_RDWR);
if (this->fbfd == -1){
LOGWARN("Unable to open /dev/fb0. Do you have a monitor connected?");
return false;
}
if (ioctl(this->fbfd, FBIOGET_VSCREENINFO, &fbinfo)){
LOGERROR("Unable to retrieve framebuffer v screen info. Are you running as root?");
return false;
}
if (ioctl(this->fbfd, FBIOGET_FSCREENINFO, &fbfixinfo)){
LOGERROR("Unable to retrieve framebuffer f screen info. Are you running as root?");
return false;
}
if (fbinfo.bits_per_pixel != 16){
LOGERROR("PowerView emulation only supports 16 bits per pixel framebuffer. Currently set to %d", fbinfo.bits_per_pixel);
return false;
}
fbbpp = fbinfo.bits_per_pixel;
fblinelen = fbfixinfo.line_length;
fb = (char *)mmap(0, fbfixinfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
if ((int)fb == -1){
LOGERROR("Unable to mmap the framebuffer memory. Are you running as root?");
return false;
}
// Clear the framebuffer
memset(this->fb, 0, fbfixinfo.smem_len);
// Hide the flashing cursor on the screen
fbcon_cursor(false);
// Disable the automatic screen blanking (screen saver)
fbcon_blank(false);
// Draw a blue frame around the display area
// This indicates that the PowerView simulation is running
ClearFrameBuffer(framebuffer_blue);
// Report status to the screen
char status_string[256];
sprintf(status_string, "PowerView initialized on %dx%d %d bpp framebuffer\r", fbinfo.xres, fbinfo.yres, fbinfo.bits_per_pixel);
fbcon_text(status_string);
LOGINFO(status_string);
return true;
}
void SCSIPowerView::Open(const Filepath& path)
{
}
//---------------------------------------------------------------------------
//
// INQUIRY
@ -511,20 +460,6 @@ int SCSIPowerView::Inquiry(const DWORD *cdb, BYTE *buf)
}
//---------------------------------------------------------------------------
//
// READ
//
//---------------------------------------------------------------------------
int SCSIPowerView::Read(const DWORD *cdb, BYTE *buf, uint64_t block)
{
int rx_packet_size = 0;
return rx_packet_size;
}
bool SCSIPowerView::WriteConfiguration(const DWORD *cdb, const BYTE *buf, const DWORD length)
{
@ -701,16 +636,16 @@ bool SCSIPowerView::WriteFrameBuffer(const DWORD *cdb, const BYTE *buf, const DW
switch(color_depth){
case eColorDepth_t::eColorsBW:
sprintf(newstring, " Black & White %04X - %u x %u \r", color_depth, screen_width_px, screen_height_px);
sprintf(newstring, " Black & White %04X - %u x %u \r", color_depth, screen_width_px, screen_height_px);
break;
case eColorDepth_t::eColors16:
sprintf(newstring, " 16 colors/grays %04X - %u x %u \r", color_depth, screen_width_px,screen_height_px );
sprintf(newstring, " 16 colors/grays %04X - %u x %u \r", color_depth, screen_width_px,screen_height_px );
break;
case eColorDepth_t::eColors256:
sprintf(newstring, " 256 colors/grays %04X - %u x %u \r", color_depth, screen_width_px, screen_height_px);
sprintf(newstring, " 256 colors/grays %04X - %u x %u \r", color_depth, screen_width_px, screen_height_px);
break;
default:
sprintf(newstring, " UNKNOWN COLOR DEPTH!! %04X - %u x %u \r", color_depth, screen_width_px, screen_height_px);
sprintf(newstring, " UNKNOWN COLOR DEPTH!! %04X - %u x %u \r", color_depth, screen_width_px, screen_height_px);
break;
}
fbcon_text(newstring);
@ -862,92 +797,3 @@ bool SCSIPowerView::WriteFrameBuffer(const DWORD *cdb, const BYTE *buf, const DW
return true;
}
//https://www.i-programmer.info/programming/cc/12839-applying-c-framebuffer-graphics.html?start=1
void SCSIPowerView::SetPixel(uint32_t x, uint32_t y, uint32_t r,
uint32_t g, uint32_t b) {
// char newstr[1024];
uint32_t pixel = (r << fbinfo.red.offset)|
(g << fbinfo.green.offset)|
(b << fbinfo.blue.offset);
// this->fbbpp = fbinfo.bits_per_pixel;
// this->fblinelen = fbfixinfo.line_length;
// loc = ((idx_col_x + offset_col_px) * (this->fbbpp / 8)) + ((idx_row_y + offset_row_px) * fblinelen);
uint32_t location = x*fbinfo.bits_per_pixel/8 +
y*fbfixinfo.line_length;
// sprintf(newstr, "%d:%d,", x, y);
// fbcon_text(newstr);
*(fb + location) = pixel & 0xFF;
*(fb + location) = (pixel >> 8) & 0xFF;
}
//---------------------------------------------------------------------------
//
// Write
//
// Command: 0a 00 00 LL LL XX (LLLL is data length, XX = 80 or 00)
// Function: Write a packet at a time to the device (standard SCSI Write)
// Type: Output; the format of the data to be sent depends on the value
// of XX, as follows:
// - if XX = 00, LLLL is the packet length, and the data to be sent
// must be an image of the data packet
// - if XX = 80, LLLL is the packet length + 8, and the data to be
// sent is:
// PP PP 00 00 XX XX XX ... 00 00 00 00
// where:
// PPPP is the actual (2-byte big-endian) packet length
// XX XX ... is the actual packet
//
//---------------------------------------------------------------------------
bool SCSIPowerView::Write(const DWORD *cdb, const BYTE *buf, const DWORD length)
{
BYTE data_format = cdb[5];
// WORD data_length = (WORD)cdb[4] + ((WORD)cdb[3] << 8);
if (data_format == 0x00){
// m_tap->Tx(buf, data_length);
// LOGTRACE("%s Transmitted %u bytes (00 format)", __PRETTY_FUNCTION__, data_length);
return true;
}
else if (data_format == 0x80){
// // The data length is specified in the first 2 bytes of the payload
// data_length=(WORD)buf[1] + ((WORD)buf[0] << 8);
// m_tap->Tx(&buf[4], data_length);
// LOGTRACE("%s Transmitted %u bytes (80 format)", __PRETTY_FUNCTION__, data_length);
return true;
}
else
{
// LOGWARN("%s Unknown data format %02X", __PRETTY_FUNCTION__, (unsigned int)command->format);
LOGWARN("%s Unknown data format %02X", __PRETTY_FUNCTION__, (unsigned int)data_format);
return true;
}
}
bool SCSIPowerView::ReceiveBuffer(int len, BYTE *buffer)
{
int row = 0;
int col = 0;
for (int i = 0; i < len; i++) {
unsigned char j = reverse_table[buffer[i]];
for (int bit = 0; bit < 8; bit++) {
int loc = (col * (this->fbbpp / 8)) + (row * this->fblinelen);
col++;
if (col % this->screen_width_px == 0) {
col = 0;
row++;
}
*(this->fb + loc) = (j & (1 << bit)) ? 0 : 255;
*(this->fb + loc + 1) = (j & (1 << bit)) ? 0 : 255;
*(this->fb + loc + 2) = (j & (1 << bit)) ? 0 : 255;
}
}
return TRUE;
}

View File

@ -47,37 +47,26 @@ private:
enum eColorDepth_t : uint16_t {eColorsNone=0x0000, eColorsBW=0x0001, eColors16=0x0010, eColors256=0x0100};
eColorDepth_t color_depth;
void AddCommand(SCSIDEV::scsi_command, const char*, void (SCSIPowerView::*)(SASIDEV *));
void dump_command(SASIDEV *controller);
// Largest framebuffer supported by the Radius PowerView is 800x600 at 16-bit color (2 bytes per pixel)
// Largest framebuffer supported by the Radius PowerView is 800x600 at 256 colors (1 bytes per pixel)
// Double it for now, because memory is cheap....
// TODO: Remove the "*2" from this
const int POWERVIEW_BUFFER_SIZE = (800 * 600 * 2);
DWORD m_powerview_resolution_x;
DWORD m_powerview_resolution_y;
void fbcon_cursor(bool blank);
void fbcon_blank(bool blank);
void fbcon_text(char* message);
void SetPixel(uint32_t x, uint32_t y, uint32_t r, uint32_t g, uint32_t b);
public:
SCSIPowerView();
~SCSIPowerView();
bool Init(const map<string, string>&) override;
void Open(const Filepath& path) override;
// // Commands
int Inquiry(const DWORD *cdb, BYTE *buffer) override;
int Read(const DWORD *cdb, BYTE *buf, uint64_t block) override;
bool Write(const DWORD *cdb, const BYTE *buf, const DWORD length);
bool WriteFrameBuffer(const DWORD *cdb, const BYTE *buf, const DWORD length);
bool WriteColorPalette(const DWORD *cdb, const BYTE *buf, const DWORD length);
bool WriteConfiguration(const DWORD *cdb, const BYTE *buf, const DWORD length);
@ -91,15 +80,14 @@ public:
bool Dispatch(SCSIDEV *) override;
bool ReceiveBuffer(int len, BYTE *buffer);
private:
void ClearFrameBuffer(DWORD blank_color);
private:
uint32_t screen_width_px;
uint32_t screen_height_px;
// Default to the lowest resolution supported by the PowerView (640x400)
uint32_t screen_width_px = 640;
uint32_t screen_height_px = 400;
eColorDepth_t color_depth = eColorsNone;
struct fb_var_screeninfo fbinfo;
struct fb_fix_screeninfo fbfixinfo;
@ -117,14 +105,14 @@ private:
int fbfd;
char *fb;
int fbwidth;
int fbheight;
int fblinelen;
int fbsize;
int fbbpp;
// Hard-coded inquiry response to match the real PowerView
static const BYTE m_inquiry_response[];
static unsigned char reverse_table[256];
DWORD framebuffer_black;
DWORD framebuffer_blue;
DWORD framebuffer_yellow;