Files
FireBee_SVN/usb/store/xhdi.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;
}