Skip to content
This repository was archived by the owner on Dec 23, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
194 changes: 130 additions & 64 deletions Kernel/dev/cpc/ch375.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,82 +19,148 @@
* as 1,5us wont be a problem in many cases
*/

#include <kernel.h>
#include <printf.h>
#include "ch375.h"


#include <kernel.h>
#include <tinydisk.h>
#include <printf.h>

#define _CH375_PRIVATE

#include "ch375.h"


#ifdef CONFIG_CH375

static uint8_t ch_rd = CH375_CMD_RD_USB_DATA;
static uint8_t ch_wd = CH375_CMD_WR_USB_DATA7;
uint8_t ch_rd = CH375_CMD_RD_USB_DATA;
uint8_t ch_wd = CH375_CMD_WR_USB_DATA7;

/* Some guesswork here on how the get status polling is meant to work */
uint8_t ch375_rpoll(void)
uint8_t ch375_rdata(uint8_t dev)
{
uint16_t count = 0x8000;
uint8_t r;
while(--count && ((ch375_rstatus() & 0x80) != 0)) nap2();
if (count == 0) {
kprintf("ch375: timeout.\n");
return 0xFF;
/*kprintf("ch375_rdata: %u\n", dev);*/
if (ch375_comm_type[dev] == CH375_COMM_SERIAL)
{
while(--count && (in16(ch375_sports[dev]) == CH375_SERIAL_WAIT));
if (count == 0) {
kprintf("ch375_serial: timeout.\n");
return 0xFF;
}
}
/* Get interrupt status, and clear interrupt */
ch375_wcmd(CH375_CMD_GET_STATUS);
nap2();
r = ch375_rdata();
/* kprintf("ch375_rpoll %2x", r); */;
return r;
return in16(ch375_dports[dev]);
}

uint8_t ch375_rstatus(uint8_t dev)
{
/*kprintf("ch375_rstatus: %u\n", dev);*/
switch (ch375_comm_type[dev])
{
case CH375_COMM_PARALLEL:
return in16(ch375_sports[dev]);
break;
case CH375_COMM_SERIAL:
return ch375_rdata(dev);
break;
default:
break;
}
}

int ch375_xfer(uint_fast8_t dev, bool is_read, uint32_t lba, uint8_t *dptr)
void ch375_wdata(uint8_t dev, uint8_t data)
{
uint_fast8_t n = 0;
uint_fast8_t r;
out16(ch375_dports[dev], data);
/*kprintf("ch375_wdata: %u, %2x\n", dev, data);*/
}

if (is_read)
ch375_wcmd(CH375_CMD_DISK_READ);
else
ch375_wcmd(CH375_CMD_DISK_WRITE);
nap2();
ch375_wdata(lba);
ch375_wdata(lba >> 8);
ch375_wdata(lba >> 16);
ch375_wdata(lba >> 24);
ch375_wdata(1);
for (n = 0; n < 8; n++) {
r = ch375_rpoll();
if (is_read) {
if (r != CH375_USB_INT_DISK_READ)
return 0;
ch375_wcmd(ch_rd);
nap2();
r = ch375_rdata(); /* Throw byte count away - always 64 */
if (r != 64) {
/* kprintf("weird rd len %d\n", r); */
return 0;
}
ch375_rblock(dptr);
ch375_wcmd(CH375_CMD_DISK_RD_GO);
} else {
if (r != CH375_USB_INT_DISK_WRITE)
return 0;
ch375_wcmd(ch_wd);
nap2();
ch375_wdata(0x40); /* Send write count */
ch375_wblock(dptr);
ch375_wcmd(CH375_CMD_DISK_WR_GO);
}
dptr += 0x40;
}
r = ch375_rpoll();
if (r != CH375_USB_INT_SUCCESS) {
kprintf("ch375: error %d\n", r);
return 0;
void ch375_wcmd(uint8_t dev, uint8_t cmd)
{
/*kprintf("ch375_wcmd: %u, %2x\n", dev, cmd);*/
switch (ch375_comm_type[dev])
{
case CH375_COMM_PARALLEL:
out16(ch375_sports[dev], cmd);
break;
case CH375_COMM_SERIAL:
ch375_wdata(dev, 0x57);
ch375_wdata(dev, 0xAB);
ch375_wdata(dev, cmd);
break;
}
return 1;
}

#endif

/* Some guesswork here on how the get status polling is meant to work */
uint8_t ch375_rpoll(uint_fast8_t dev)
{
uint16_t count = 0x8000;
uint8_t r;
while(--count && ((((r = ch375_rstatus(dev)) & 0x80) != 0 ))) nap2();
if (count == 0) {
kprintf("ch375: timeout. rstat=%2x\n", r);
return 0xFF;
}
/*kprintf("rstat=%2x\n", r);*/
/* Get interrupt status, and clear interrupt */
ch375_wcmd(dev, CH375_CMD_GET_STATUS);
nap2();
r = ch375_rdata(dev);
/*kprintf("ch375_rpoll %u,%u,%2x\n", dev, count, r);*/
return r;
}

int ch375_xfer(uint_fast8_t dev, bool is_read, uint32_t lba, uint8_t *dptr)
{
uint_fast8_t n = 0;
uint_fast8_t r;

td_io_data_reg = ch375_dports[dev];
td_io_data_count = 8;
/*kprintf("dr:%x\n",ch375_data_reg);*/
if (is_read)
ch375_wcmd(dev, CH375_CMD_DISK_READ);
else
ch375_wcmd(dev, CH375_CMD_DISK_WRITE);
nap2();
ch375_wdata(dev, lba);
ch375_wdata(dev, lba >> 8);
ch375_wdata(dev, lba >> 16);
ch375_wdata(dev, lba >> 24);
ch375_wdata(dev, 1);
for (n = 0; n < 8; n++) {
r = ch375_rpoll(dev);
if (is_read) {
/*kprintf("rd %u\n", n);*/
if (r != CH375_USB_INT_DISK_READ){
/*kprintf("r != CH375_USB_INT_DISK_READ = %2x\n", r);*/
continue;
}
ch375_wcmd(dev, ch_rd);
nap2();
r = ch375_rdata(dev); /* Throw byte count away - always 64 */
if (r != 64) {
kprintf("weird rd len %d\n", r);
continue;
}
/*kprintf("rblock(%x)\n", dptr);*/
td_io_rblock(dptr);
ch375_wcmd(dev, CH375_CMD_DISK_RD_GO);
} else {
/*kprintf("wr\n");*/
if (r != CH375_USB_INT_DISK_WRITE)
continue;
ch375_wcmd(dev, ch_wd);
nap2();
ch375_wdata(dev, 0x40); /* Send write count */
td_io_wblock(dptr);
ch375_wcmd(dev, CH375_CMD_DISK_WR_GO);
}
dptr += 0x40;
}
r = ch375_rpoll(dev);
if (r != CH375_USB_INT_SUCCESS) {
kprintf("ch375: error %d\n", r);
return 0;
}
return 1;
}


#endif
26 changes: 18 additions & 8 deletions Kernel/dev/cpc/ch375.h
Original file line number Diff line number Diff line change
@@ -1,36 +1,46 @@
#ifndef _CH375_H
#define _CH375_H
#ifndef CH375_H
#define CH375_H

#include "plt_ch375.h"

#define CH375_CMD_GET_IC_VER 0x01
#define CH375_CMD_SET_BAUDRATE 0x02
#define CH375_CMD_RESET_ALL 0x05
#define CH375_CMD_CHECK_EXIST 0x06
#define CH375_CMD_SET_USB_MODE 0x15
#define CH375_CMD_TEST_CONNECT 0x16
#define CH375_CMD_GET_STATUS 0x22
#define CH375_CMD_DIRTY_BUFFER 0x25
#define CH376_CMD_RD_USB_DATA 0x27
#define CH375_CMD_RD_USB_DATA 0x28
#define CH375_CMD_WR_USB_DATA7 0x2B
#define CH376_CMD_WR_HOST_DATA 0x2C
#define CH375_CMD_DISK_CONNECT 0x30
#define CH375_CMD_DISK_MOUNT 0x31
#define CH375_CMD_CLR_STALL 0x41
#define CH375_CMD_DISK_INIT 0x51
#define CH375_CMD_DISK_RESET 0x52
#define CH375_CMD_DISK_READ 0x54
#define CH375_CMD_DISK_RD_GO 0x55
#define CH375_CMD_DISK_WRITE 0x56
#define CH375_CMD_DISK_WR_GO 0x57
#define CH375_CMD_DISK_R_SENSE 0x5A

#define CH375_USB_INT_SUCCESS 0x14
#define CH375_USB_INT_CONNECT 0x15
#define CH375_USB_INT_DISK_READ 0x1D
#define CH375_USB_INT_DISK_WRITE 0x1E

/* TODO: 2 us delay should be implemented by platform */

#ifndef nap2()
#define nap2() nap20()
#endif

uint_fast8_t ch375_probe(void);
uint8_t ch375_rpoll(void);
int ch375_xfer(uint_fast8_t dev, bool is_read, uint32_t lba, uint8_t *dptr);

extern uint_fast8_t ch375_probe(void);
extern void* td_io_data_reg;
extern uint8_t td_io_data_count;
extern void ch375_wcmd(uint8_t dev, uint8_t cmd);
extern void ch375_wdata(uint8_t dev, uint8_t data);
extern uint8_t ch375_rdata(uint8_t dev);
extern uint8_t ch375_rpoll(uint_fast8_t dev);
extern int ch375_xfer(uint_fast8_t dev, bool is_read, uint32_t lba, uint8_t *dptr);
#endif
Loading
Loading