Logo Search packages:      
Sourcecode: cbmlink version File versions  Download package

c64net.c

Go to the documentation of this file.
/**
 * @file c64net.c
 * Transfer routines for the 2-bit/4-bit PET/VIC-20/C64/C128 to PC cable
 * used by the 64NET software
 * @author Marko Mäkelä (msmakela@nic.funet.fi)
 */

/*
 * Copyright © 1994-1996 Marko Mäkelä and Olaf Seibert
 * Copyright © 2001,2002 Marko Mäkelä
 * Original Linux and Commodore 64/128/Vic-20 version by Marko Mäkelä
 * Ported to the PET and the Amiga series by Olaf Seibert
 * Restructured by Marko Mäkelä
 * 
 *     This program 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#ifdef COMM_PC
# include "info.h"
# include "c64net.h"
# include "pcpar.h"

/** Open the communication channel
 * @param dev           name of the communication device
 * @param hostinfo      (output) the computer model information
 * @return        zero on success, nonzero on failure
 */
int
c64net_init (const char* dev, struct hostinfo* hostinfo)
{
  unsigned char detectbuf[5];
  if (!open_port (dev))
    return 1;
  out_data (0);
  if (c64net_write ("", 1))
    return 1;
  if (c64net_read (detectbuf, sizeof detectbuf))
    return 2;
  hostinfo->host = detectbuf[0];
  hostinfo->driver = (unsigned) detectbuf[1] | (unsigned) detectbuf[2] << 8;
  hostinfo->basic = (unsigned) detectbuf[3] | (unsigned) detectbuf[4] << 8;
  return 0;
}

/** Close the communication channel */
void
c64net_close (void)
{
  out_data (0);
  close_port ();
}

#if !defined __BCC__ && (!defined __GNUC__ || defined USE_PPDEV)
/** Send data (unoptimised)
 * @param buf           the data to be sent
 * @param len           length of the data in bytes
 */
static void
c64net_write_slow (const void* buf, unsigned len)
{
  register const unsigned char* buffer = buf;

  while (len--) {
    out_data (*buffer | 8);
    while(0x20 & in_stat ());
    out_data (*buffer++ << 4);
    while (!(0x20 & in_stat ()));
  }
}

/** Receive data (unoptimised)
 * @param buf           the data to be received
 * @param len           length of the data in bytes
 * @return        zero on success, nonzero on failure
 */
static void
c64net_read_slow (void* buf, unsigned len)
{
  register unsigned char* buffer = buf;

  while (len--) {
    register unsigned char data;
    out_data (0xf0);
    while(0x20 & in_stat ());
    out_data (0);

    while(!(0x20 & in_stat ()));
    data = (0xc0 & in_stat ()) >> 6;
    out_data (8);

    while (0x20 & in_stat ());
    data |= (0xc0 & in_stat ()) >> 4;
    out_data (0);

    while(!(0x20 & in_stat ()));
    data |= (0xc0 & in_stat ()) >> 2;
    out_data (8);

    while (0x20 & in_stat ());
    data |= 0xc0 & in_stat ();
    out_data (0);

    *buffer++ = data ^ 0xaa;

    while (!(0x20 & in_stat ()));
  }
}
#endif /* !__BCC__ && (!__GNUC__ || USE_PPDEV) */

/** Send data
 * @param buf           the data to be sent
 * @param len           length of the data in bytes
 * @return        zero on success, nonzero on failure
 */
int
c64net_write (const void* buf, unsigned len)
{
# ifdef __GNUC__
#  ifdef USE_PPDEV
  if (baseaddr == (unsigned) -1) {
    c64net_write_slow (buf, len);
    return 0;
  }
#  endif /* USE_PPDEV */
  __asm__ volatile ("0:\t"
                "movb (%0),%%al\n\t"
                "orb $8,%%al\n\t"
                "outb %%al,%%dx\n\t"
                "incw %%dx\n"
                "1:\t"
                "inb %%dx,%%al\n\t"
                "testb $32,%%al\n\t"
                "jne 1b\n\t"
                "movb (%0),%%al\n\t"
                "salb $4,%%al\n\t"
                "decw %%dx\n\t"
                "outb %%al,%%dx\n\t"
                "incw %%dx\n"
                "2:\t"
                "inb %%dx,%%al\n\t"
                "testb $32,%%al\n\t"
                "je 2b\n\t"
                "decw %%dx\n\t"
                "inc %0\n\t"
                "loop 0b"
                : /* no outputs */
                : "b" (buf), "c" (len), "d" (baseaddr)
                : "ax");
  return 0;
# else /* BCC does not recognize #elif */
# ifdef __BCC__
#  asm
    push bp
    mov bp,sp
    push es
    mov dx,_baseaddr
    mov cx,len_
    mov bx,buf_
    mov ax,I 0x40
    mov es,ax

.sloop:
    mov al,[bx]
    or al,I 8
    out dx,al

    inc dx
.wait1:
    in al,dx
    test al,I 32
    je .nwait1
    eseg
    mov al,byte [0x71]  ; is the keyboard interrupt flag set?
    test al,I 0x80
    jz .wait1
    jmp near _abreak

.nwait1:
    mov al,[bx]
    shl al,I 1
    shl al,I 1
    shl al,I 1
    shl al,I 1
    dec dx
    out dx,al

    inc dx
.wait2:
    in al,dx
    test al,I 32
    jne .nwait2
    mov al,byte [0x71]  ; is the keyboard interrupt flag set?
    test al,I 0x80
    jz .wait2
    jmp near _abreak
.nwait2:
    dec dx

    inc bx
    loop .sloop

    pop es
    pop bp
    xor ax,ax
#  endasm
# else
  c64net_write_slow (buf, len);
  return 0;
# endif
# endif /* BCC does not recognize #elif */
}

/** Receive data
 * @param buf           the data to be received
 * @param len           length of the data in bytes
 * @return        zero on success, nonzero on failure
 */
int
c64net_read (void* buf, unsigned len)
{
# ifdef __GNUC__
#  ifdef USE_PPDEV
  if (baseaddr == (unsigned) -1) {
    c64net_read_slow (buf, len);
    return 0;
  }
#  endif /* USE_PPDEV */
  __asm__ volatile ("0:\t"
                "movb $0xf0,%%al\n\t"
                "outb %%al,%%dx\n\t"
                "incw %%dx\n"
                "1:\t"
                "inb %%dx,%%al\n\t"
                "testb $32,%%al\n\t"
                "jne 1b\n\t"
                "decw %%dx\n\t"
                "xorb %%al,%%al\n\t"
                "outb %%al,%%dx\n\t"
                "incw %%dx\n"
                "1:\t"
                "inb %%dx,%%al\n\t"
                "testb $32,%%al\n\t"
                "je 1b\n\t"
                "decw %%dx\n\t"
                "andb $0xc0,%%al\n\t"
                "shrb $6,%%al\n\t"
                "mov %%al,(%%ebx)\n\t"
                "movb $8,%%al\n\t"
                "outb %%al,%%dx\n\t"
                "incw %%dx\n"
                "1:\t"
                "inb %%dx,%%al\n\t"
                "testb $32,%%al\n\t"
                "jne 1b\n\t"
                "decw %%dx\n\t"
                "andb $0xc0,%%al\n\t"
                "shrb $4,%%al\n\t"
                "orb %%al,(%%ebx)\n\t"
                "xorb %%al,%%al\n\t"
                "outb %%al,%%dx\n\t"
                "incw %%dx\n"
                "1:\t"
                "inb %%dx,%%al\n\t"
                "testb $32,%%al\n\t"
                "je 1b\n\t"
                "decw %%dx\n\t"
                "andb $0xc0,%%al\n\t"
                "shrb $2,%%al\n\t"
                "orb %%al,(%%ebx)\n\t"
                "movb $8,%%al\n\t"
                "outb %%al,%%dx\n\t"
                "incw %%dx\n"
                "1:\t"
                "inb %%dx,%%al\n\t"
                "testb $32,%%al\n\t"
                "jne 1b\n\t"
                "decw %%dx\n\t"
                "andb $0xc0,%%al\n\t"
                "xorb $0xaa,%%al\n\t"
                "xorb %%al,(%%ebx)\n\t"
                "xorb %%al,%%al\n\t"
                "outb %%al,%%dx\n\t"
                "incw %%dx\n"
                "1:\t"
                "inb %%dx,%%al\n\t"
                "testb $32,%%al\n\t"
                "je 1b\n\t"
                "decw %%dx\n\t"
                "inc %%ebx\n\t"
                "loop 0b"
                : /* no outputs */
                : "b" (buf), "c" (len), "d" (baseaddr)
                : "ax");
  return 0;
# else /* BCC does not recognize #elif */
# ifdef __BCC__
#  asm
    push bp
    mov bp,sp
    push es
    mov dx,_baseaddr
    mov cx,len_
    mov bx,buf_
    mov ax,I 0x40
    mov es,ax

.rloop:
    mov al,I 0xf0
    out dx,al
    inc dx
.input0:
    in al,dx
    test al,I 32
    je .ninput0
    eseg
    mov al,byte [0x71]  ; is the keyboard interrupt flag set?
    test al,I 0x80
    jz .input0

.ninput0:
    dec dx

    xor al,al
    out dx,al
    inc dx

.input1:
    in al,dx
    test al,I 32
    jne .ninput1
    eseg
    mov al,byte [0x71]  ; is the keyboard interrupt flag set?
    test al,I 0x80
    jz .input1
    jmp near _abreak
.ninput1:
    dec dx
    and al,I 0xc0
    shr al,I 1
    shr al,I 1
    shr al,I 1
    shr al,I 1
    shr al,I 1
    shr al,I 1
    mov [bx],al

    mov al,I 8
    out dx,al
    inc dx

.input2:
    in al,dx
    test al,I 32
    je .ninput2
    eseg
    mov al,byte [0x71]  ; is the keyboard interrupt flag set?
    test al,I 0x80
    jz .input2
    jmp near _abreak
.ninput2:
    dec dx
    and al,I 0xc0
    shr al,I 1
    shr al,I 1
    shr al,I 1
    shr al,I 1
    or [bx],al

    xor al,al
    out dx,al
    inc dx

.input3:
    in al,dx
    test al,I 32
    jne .ninput3
    eseg
    mov al,byte [0x71]  ; is the keyboard interrupt flag set?
    test al,I 0x80
    jz .input3
    jmp near _abreak
.ninput3:
    dec dx
    and al,I 0xc0
    shr al,I 1
    shr al,I 1
    or [bx],al

    mov al,I 8
    out dx,al
    inc dx

.input4:
    in al,dx
    test al,I 32
    je .ninput4
    eseg
    mov al,byte [0x71]  ; is the keyboard interrupt flag set?
    test al,I 0x80
    jz .input4
    jmp near _abreak
.ninput4:
    dec dx
    and al,I 0xc0
    xor al,I 0xaa
    xor [bx],al

    xor al,al
    out dx,al
    inc dx

.input5:
    in al,dx
    test al,I 32
    jne .ninput5
    eseg
    mov al,byte [0x71]  ; is the keyboard interrupt flag set?
    test al,I 0x80
    jz .input5
    jmp near _abreak
.rlop:
    jmp near .rloop     ; otherwise the branch would be out of range
.ninput5:
    dec dx

    inc bx
    loop .rlop          ; otherwise the branch would be out of range
    pop es
    pop bp
    xor ax,ax
#  endasm
# else
  c64net_read_slow (buf, len);
  return 0;
# endif
# endif /* BCC does not recognize #elif */
}

#endif /* COMM_PC */

Generated by  Doxygen 1.6.0   Back to index