392 lines
10 KiB
C
392 lines
10 KiB
C
/***************** NOT READY YET ***********************/
|
|
/**************** ONLY EXPERIMENTAL ********************/
|
|
|
|
/* TOS 4.04 Xbios dispatcher for the CT60/CTPCI boards
|
|
* and USB-disk / Ram-Disk utility
|
|
* Didier Mequignon 2005-2009, e-mail: aniplay@wanadoo.fr
|
|
*
|
|
* Translation to C by David Galvez. 2010, e-mail: dgalvez75@gmail.com
|
|
*
|
|
* This file is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This file is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <mint/osbind.h>
|
|
|
|
#include "config.h"
|
|
#include "vars.h"
|
|
#include "xhdi.h"
|
|
#include "debug.h"
|
|
|
|
long *drvbits = (long *)_DRVBITS;
|
|
|
|
struct pun_info *old_pun_ptr = (struct pun_info *)0x512;
|
|
struct usb_pun_info pun_ptr_usb;
|
|
|
|
XBRA xbra_hdv_bpb;
|
|
XBRA xbra_hdv_rw;
|
|
XBRA xbra_hdv_mediach;
|
|
|
|
extern long usb_1st_disk_drive;
|
|
extern short max_logical_drive;
|
|
|
|
extern unsigned long usb_stor_read(int device, unsigned long blknr, unsigned long blkcnt, void *buffer);
|
|
|
|
void drive_full_usb(void)
|
|
{
|
|
DEBUG_XHDI("\n");
|
|
}
|
|
|
|
long __CDECL hdv_bpb_usb(void)
|
|
{
|
|
unsigned short dev;
|
|
long r;
|
|
|
|
__asm__ volatile /* get arguments from the stack */
|
|
(
|
|
"move.w 12(%%sp),%0\n\t"
|
|
|
|
:/*outputs*/ "=m" (dev)
|
|
:/*inputs*/
|
|
);
|
|
|
|
__asm__ volatile /* call old vector */
|
|
(
|
|
"movem.l %%d2-%%d7/%%a2-%%a6,-(%%sp)\n\t" /* important to save register */
|
|
"move.l %1,%%a0\n\t"
|
|
"move.w #0,-(%%sp)\n\t"
|
|
"move.w %2,-(%%sp)\n\t"
|
|
"jsr (%%a0)\n\t"
|
|
"addq.l #4,%%sp\n\t"
|
|
"move.l %%d0,%0\n\t"
|
|
"movem.l (%%sp)+,%%d2-%%d7/%%a2-%%a6\n\t"
|
|
:/*outputs*/ "=r" (r)
|
|
:/*inputs*/ "m" (xbra_hdv_bpb.xb_oldvec), "m" (dev)
|
|
:"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "a2", "a3", "a4", "a5" /*clobbered regs*/
|
|
);
|
|
return r;
|
|
}
|
|
|
|
long __CDECL hdv_rw_usb(void)
|
|
{
|
|
void *buf;
|
|
short count, recno, dev, mode;
|
|
long lrecno;
|
|
|
|
long r = 0;
|
|
|
|
__asm__ volatile /* get arguments from the stack */
|
|
(
|
|
"move.l 18(%%sp),%0\n\t"
|
|
"move.w 14(%%sp),%1\n\t"
|
|
"move.w 12(%%sp),%2\n\t"
|
|
"move.w 10(%%sp),%3\n\t"
|
|
"move.l 8(%%sp),%4\n\t"
|
|
"move.w 4(%%sp),%5\n\t"
|
|
:/*outputs*/ "=r" (lrecno), "=r" (dev) ,"=r" (recno), "=r" (count), "=r" (buf), "=r" (mode)
|
|
:/*inputs*/
|
|
);
|
|
|
|
DEBUG_XHDI("lrecno %lx dev %d recno %x count %d mode %x\n",
|
|
lrecno, dev, recno, count, mode);
|
|
|
|
DEBUG_XHDI("\n");
|
|
DEBUG_XHDI("rw\n");
|
|
|
|
__asm__ volatile /* call old vector */
|
|
(
|
|
"movem.l %%d2-%%d7/%%a2-%%a6,-(%%sp)\n\t"
|
|
"move.l %1,%%a0\n\t"
|
|
"move.l (%%a0),%%d0\n\t"
|
|
"move.w #0,-(%%sp)\n\t"
|
|
"move.l %2,-(%%sp)\n\t"
|
|
"move.w %3,-(%%sp)\n\t"
|
|
"move.w %4,-(%%sp)\n\t"
|
|
"move.w %5,-(%%sp)\n\t"
|
|
"move.l %6,-(%%sp)\n\t"
|
|
"move.w %7,-(%%sp)\n\t"
|
|
"move.l %%d0,%%a0\n\t"
|
|
"jsr (%%a0)\n\t"
|
|
"addq.l #4,%%sp\n\t"
|
|
"move.l %%d0,%0\n\t"
|
|
"movem.l (%%sp)+,%%d2-%%d7/%%a2-%%a6\n\t"
|
|
:/*outputs*/ "=r" (r)
|
|
:/*inputs*/ "r" (xbra_hdv_rw.xb_oldvec), "r" (lrecno), "r" (dev) ,"r" (recno), "r" (count), "r" (buf), "r" (mode)
|
|
:"d0"/*, "d1", "d2", "d3", "d4", "d5", "d6", "d7", "a2", "a3", "a4", "a5" clobbered regs*/
|
|
);
|
|
|
|
// r = (*xbra_hdv_rw.xb_oldvec)(mode, buf, num, recno, dev, l);
|
|
DEBUG_XHDI (" r %lx \n", r);
|
|
|
|
return r;
|
|
}
|
|
|
|
long __CDECL hdv_mediach_usb(void)
|
|
{
|
|
DEBUG_XHDI("\n");
|
|
DEBUG_XHDI("mediach\n");
|
|
|
|
short dev, dev1, dev2;
|
|
long r;
|
|
|
|
__asm__ volatile /* get arguments from the stack */
|
|
(
|
|
"move.w 2(%%sp),%0\n\t"
|
|
"move.w 4(%%sp),%1\n\t"
|
|
"move.w 6(%%sp),%2\n\t"
|
|
:/*outputs*/ "=r" (dev), "=r" (dev1), "=r" (dev2)
|
|
:/*inputs*/
|
|
);
|
|
|
|
DEBUG_XHDI (" dev(2) %x dev(4) %x dev(6) %x\n", dev, dev1, dev2);
|
|
|
|
__asm__ volatile /* call old vector */
|
|
(
|
|
"movem.l %%d2-%%d7/%%a2-%%a6,-(%%sp)\n\t"
|
|
"move.l %1,%%a0\n\t"
|
|
"move.l (%%a0),%%d0\n\t"
|
|
"move.w #0,-(%%sp)\n\t"
|
|
"move.w %2,-(%%sp)\n\t"
|
|
"move.l %%d0,%%a0\n\t"
|
|
"jsr (%%a0)\n\t"
|
|
"addq.l #4,%%sp\n\t"
|
|
"move.l %%d0,%0\n\t"
|
|
"movem.l (%%sp)+,%%d2-%%d7/%%a2-%%a6\n\t"
|
|
:/*outputs*/ "=r" (r)
|
|
:/*inputs*/ "r" (xbra_hdv_mediach.xb_oldvec), "r" (dev)
|
|
:"d0"/*, "d1", "d2", "d3", "d4", "d5", "d6", "d7", "a2", "a3", "a4", "a5" clobbered regs*/
|
|
);
|
|
// printf (" r %lx \n", r);
|
|
// r = (*xbra_hdv_mediach.xb_oldvec)(d);
|
|
// DEBUG_XHDI("Calling vector: %x\n", xbra_hdv_mediach.xb_oldvec);
|
|
// r = (*xbra_hdv_mediach.xb_oldvec)(5);
|
|
DEBUG_XHDI(" r %lx \n", r);
|
|
|
|
return r;
|
|
}
|
|
|
|
void install_xbra(XBRA *xbra_hd, long id, long old_vec, long (*handle)())
|
|
{
|
|
DEBUG_XHDI("\n");
|
|
#define XBRA_MAGIC 0x58425241L /* "XBRA" */
|
|
#define JMP_OPCODE 0x4EF9
|
|
|
|
xbra_hd->xb_magic = XBRA_MAGIC;
|
|
xbra_hd->xb_id = id;
|
|
xbra_hd->xb_oldvec = *((Func *)old_vec);
|
|
xbra_hd->jump = JMP_OPCODE;
|
|
xbra_hd->handle = (Func) handle;
|
|
|
|
*((Func *)old_vec) = xbra_hd->handle;
|
|
|
|
DEBUG_XHDI("id: %x xbra_hd->xb_oldvec %x old_vec %x old_vec (*) %x old_vec (&) %x\n",
|
|
xbra_hd->xb_id, xbra_hd->xb_oldvec, old_vec, *((Func *)old_vec), &old_vec);
|
|
|
|
__asm__ volatile /* clean cache ??? */
|
|
(
|
|
"cpusha BC\n\t"
|
|
:/*outputs*/
|
|
:/*inputs*/
|
|
);
|
|
}
|
|
|
|
void usb_drive_ok(void)
|
|
{
|
|
DEBUG_XHDI("\n");
|
|
|
|
}
|
|
|
|
|
|
long install_usb_partition(unsigned char drive, int dev_num, unsigned long part_type,
|
|
unsigned long part_offset, unsigned long part_size)
|
|
{
|
|
DEBUG_XHDI("\n");
|
|
|
|
int *dskbufp = (int *)DSKBUFP;
|
|
unsigned short status_register;
|
|
|
|
long old_hdv_bpb;
|
|
long old_hdv_rw;
|
|
long old_hdv_mediach;
|
|
|
|
if (drive < 16) {
|
|
(pun_ptr_usb.puns)++;
|
|
pun_ptr_usb.pun[drive] = dev_num | PUN_USB;
|
|
pun_ptr_usb.pstart[drive] = part_offset;
|
|
pun_ptr_usb.ptype[drive] = part_type;
|
|
pun_ptr_usb.psize[drive] = part_size;
|
|
/* flags B15:swap, B7:change, B0:bootable */
|
|
#define BOOTABLE 0x0001
|
|
#define CHANGE 0x0080
|
|
#define SWAP 0x8000
|
|
pun_ptr_usb.flags[drive] = CHANGE;
|
|
}
|
|
|
|
if (drive < 16) {
|
|
old_pun_ptr->puns++;
|
|
old_pun_ptr->pun[drive] = dev_num | PUN_USB;
|
|
}
|
|
|
|
if (usb_stor_read (dev_num, part_offset, 1, (void *)(*dskbufp)) == 0)
|
|
return -1;
|
|
|
|
if (usb_1st_disk_drive)
|
|
usb_drive_ok();
|
|
|
|
usb_1st_disk_drive = drive;
|
|
|
|
long r;
|
|
r = (long)Getbpb (2);
|
|
DEBUG_XHDI("Before int. Getbpb return: %x \n", r);
|
|
|
|
|
|
__asm__ volatile /* mask interrupts */
|
|
(
|
|
"move.w %%sr,%%d0\n\t"
|
|
"move.w %%d0,%0\n\t"
|
|
"or.l #0x700,%%d0\n\t"
|
|
"move.w %%d0,%%sr\n\t"
|
|
:/*outputs*/ "=r" (status_register)
|
|
:/*inputs*/
|
|
:"d0" /*clobbered regs*/
|
|
);
|
|
|
|
#define _USB 0x5F555342 /* _USB */
|
|
long id = _USB;
|
|
old_hdv_bpb = (long)HDV_BPB;
|
|
|
|
DEBUG_XHDI("id: %x old_hdv_bpb %x old_hdv_bpb (*) %x hdv_bpb_usb %x\n",
|
|
id, old_hdv_bpb, *((Func *)old_hdv_bpb), hdv_bpb_usb);
|
|
install_xbra(&xbra_hdv_bpb, id, old_hdv_bpb, hdv_bpb_usb);
|
|
DEBUG_XHDI("id: %x old_hdv_bpb %x old_hdv_bpb (*) %x hdv_bpb_usb %x\n",
|
|
xbra_hdv_bpb.xb_id, xbra_hdv_bpb.xb_oldvec, *((Func *)xbra_hdv_bpb.xb_oldvec), xbra_hdv_bpb.handle);
|
|
#if 0
|
|
old_hdv_rw = (long)HDV_RW;
|
|
DEBUG_XHDI("id: %x old_hdv_rw %x old_hdv_rw (*) %x hdv_rw_usb %x\n",
|
|
id, old_hdv_rw, *((Func *)old_hdv_rw), hdv_rw_usb);
|
|
install_xbra(&xbra_hdv_rw, id, old_hdv_rw, hdv_rw_usb);
|
|
DEBUG_XHDI("id: %x old_hdv_rw %x old_hdv_rw (*) %x hdv_rw_usb %x\n",
|
|
xbra_hdv_rw.xb_id, xbra_hdv_rw.xb_oldvec, *((Func *)xbra_hdv_rw.xb_oldvec), xbra_hdv_rw.handle);
|
|
|
|
old_hdv_mediach = (long)HDV_MEDIACH;
|
|
DEBUG_XHDI("id: %x old_hdv_mediach %x old_hdv_mediach (*) %x hdv_mediach_usb %x\n",
|
|
id, old_hdv_mediach, *((Func *)old_hdv_mediach), hdv_mediach_usb);
|
|
install_xbra(&xbra_hdv_mediach, id, old_hdv_mediach, hdv_mediach_usb);
|
|
DEBUG_XHDI("id: %x old_hdv_mediach %x old_hdv_mediach (*) %x hdv_mediach_usb %x\n",
|
|
xbra_hdv_mediach.xb_id, xbra_hdv_mediach.xb_oldvec, *((Func *)xbra_hdv_mediach.xb_oldvec), xbra_hdv_mediach.handle);
|
|
#endif
|
|
|
|
r = (long)Getbpb (4);
|
|
|
|
DEBUG_XHDI("Before int. Getbpb return: %x \n", r);
|
|
|
|
// Bconin(DEV_CONSOLE);
|
|
__asm__ volatile /* restore interrupts */
|
|
(
|
|
"move.w %%sr,%%d0\n\t"
|
|
"and.w %0,%%d0\n\t"
|
|
"move.w %%d0,%%sr\n\t"
|
|
:/*outputs*/
|
|
:/*inputs*/ "r" (status_register)
|
|
:"d0"
|
|
);
|
|
DEBUG_XHDI("after restore interrups\n");
|
|
// Bconin(DEV_CONSOLE);
|
|
return 0;
|
|
}
|
|
|
|
unsigned char search_empty_drive(int dev_num, unsigned long part_type,
|
|
unsigned long part_offset, unsigned long part_size)
|
|
{
|
|
DEBUG_XHDI("\n");
|
|
|
|
unsigned char drive = 2;
|
|
|
|
DEBUG_XHDI("drvbits: %x\n", *drvbits);
|
|
while (drive < MAX_LOGICAL_DRIVE) {
|
|
if (!(*drvbits & (0x00000001 << drive))) {
|
|
DEBUG_XHDI("drive: %d\n", drive);
|
|
if (install_usb_partition(drive, dev_num, part_type, part_offset, part_size) == -1) {
|
|
DEBUG_XHDI("Couldn't install USB partition\n");
|
|
return -1;
|
|
}
|
|
else return drive;
|
|
}
|
|
drive++;
|
|
}
|
|
printf("all drives already used!\n\r");
|
|
|
|
return -1;
|
|
}
|
|
|
|
unsigned char add_partition(int dev_num, unsigned long part_type,
|
|
unsigned long part_offset, unsigned long part_size)
|
|
{
|
|
DEBUG_XHDI("\n");
|
|
|
|
unsigned char i;
|
|
unsigned char drive;
|
|
|
|
pun_ptr_usb.puns = 0x0000;
|
|
pun_ptr_usb.version_num = 0x0300;
|
|
pun_ptr_usb.max_sect_siz = 0x4000;
|
|
|
|
for (i=0; i<16; i++)
|
|
pun_ptr_usb.pun[i] = 0xff;
|
|
|
|
if ((drive = search_empty_drive(dev_num, part_type, part_offset, part_size)) == -1)
|
|
return -1;
|
|
return drive;
|
|
}
|
|
|
|
int install_usb_stor(int dev_num, unsigned long part_type,
|
|
unsigned long part_offset, unsigned long part_size,
|
|
char *vendor, char *revision, char *product )
|
|
{
|
|
DEBUG_XHDI("\n");
|
|
unsigned char part_num;
|
|
|
|
if (dev_num <= PUN_DEV) { /* Max. of 32 USB storage devices */
|
|
switch (part_type) { /* Although real limit is 16 of pinfo struct */
|
|
case GEM:
|
|
break;
|
|
case BGM:
|
|
break;
|
|
case RAW:
|
|
break;
|
|
case FAT16_32MB:
|
|
break;
|
|
case FAT16:
|
|
break;
|
|
case FAT16_WIN95:
|
|
break;
|
|
case FAT32:
|
|
break;
|
|
case FAT32_II:
|
|
break;
|
|
default:
|
|
printf("Invalid partition type (0x%08lx)\r\n", part_type);
|
|
return -1;
|
|
}
|
|
if ((part_num = add_partition(dev_num, part_type, part_offset, part_size)) == -1)
|
|
return -1;
|
|
else return 0;
|
|
}
|
|
printf("Maxim number(%d) of USB storage device reached \n\r", dev_num);
|
|
return -1;
|
|
}
|
|
|
|
|