/***************** 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 #include #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; }