Files
m68k-bdm/m68k/driver/openbsd/openbsd-bdm.c
Bernd Mueller adfd70813f initial push
2026-06-17 13:44:30 +02:00

444 lines
10 KiB
C

/*
* Motorola Background Debug Mode Driver
* Copyright (C) 2000 James Housley
* Copyright (C) 2000 Chris Johns
*
* 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.
*
* FreeBSD support by: (Started May 9, 2000)
* James Housley
* The Housleys dot Net
* 65 Frank's Lane
* Hanover, MA 02339, USA
*
* jim@thehousleys.net
*
* Chris Johns & Greg Tunnock
* Redfern Broadband Networks.
* Continued FreeBSD port, Sep 2000
* This porting effort has been made possible by Redfern Broadband
* Networks.
*
* ccj@acm.org
*
*/
#define BDM_DEFAULT_DEBUG 0
#include <sys/param.h>
#include <sys/fcntl.h>
#include <sys/systm.h>
#include <sys/ioctl.h>
#include <sys/exec.h>
#include <sys/conf.h>
#include <sys/lkm.h>
#include <sys/proc.h>
#include <sys/buf.h>
#include <sys/kernel.h>
#include <sys/uio.h>
#include <sys/syslog.h>
#include <uvm/uvm.h>
#include <uvm/uvm_param.h>
#include <uvm/uvm_pmap.h>
#include <sys/errno.h>
#include <sys/ioccom.h>
/*
************************************************************************
* OpenBSD Driver Structures *
************************************************************************
*/
#define UNIT(d) ((unsigned int)(minor(d) & 0x07))
/*
************************************************************************
* UNIX driver support routines *
************************************************************************
*/
/*
* Function prototypes.
*/
static int init_module (void);
static void os_lock_module (void);
static void os_unlock_module (void);
static int bdmprobe (void);
static void bdmattach (void);
static void bdmdetach (void);
static void bdm_outb (int port, int value);
/*
* Delay for a while so target can keep up.
*/
static void
bdm_delay (int counter)
{
while (counter--) {
__asm volatile ("nop");
}
}
/*
* Wait a longer while .
*/
static char BDMsleep;
static void
bdm_sleep (u_int time)
{
tsleep((void *)&BDMsleep, ((PZERO + 8)| PCATCH), "bdmslp", (int)time);
}
/*
************************************************************************
* OS worker functions. *
************************************************************************
*/
static int
os_claim_io_ports (char *name, unsigned int base, unsigned int num)
{
return 0;
}
static int
os_release_io_ports (unsigned int base, unsigned int num)
{
return 0;
}
static int
os_copy_in (void *dst, void *src, int size)
{
(void)memcpy(dst, src, (size_t)size);
return 0;
}
static int
os_copy_out (void *dst, void *src, int size)
{
(void)memcpy(dst, src, (size_t)size);
return 0;
}
/**
* Moves data from user-space address to kernel-space address.
*
* This is provide for Operating Systems with separate move and copy
* strategies. If an OS doesn't have a move strategy this function will
* be the same as os_copy_in().
*
* Param dst Kernel-space address to copy to.
* Param src User-space address to copy from.
* Param size Number of bytes to copy.
*
* Returns 0 if successful.
*/
static int
os_move_in (void *dst, void *src, int size)
{
return uiomove((caddr_t)dst, size, (struct uio *)src);
}
#define BUF_INCREMENTED_BY_MOVE_IN
/**
* Moves data from kernel-space address to user-space address.
*
* This is provide for Operating Systems with separate move and copy
* strategies. If an OS doesn't have a move strategy this function will
* be the same as os_copy_out().
*
* Param dst User-space address to copy to.
* Param src Kernel-space address to copy from.
* Param size Number of bytes to copy.
*
* Returns 0 if successful.
*/
static int
os_move_out (void *dst, void *src, int size)
{
return uiomove((caddr_t)src, size, (struct uio *)dst);
}
#define BUF_INCREMENTED_BY_MOVE_OUT
static void
os_lock_module ()
{
}
static void
os_unlock_module ()
{
}
/*
* Big hack to get around differences in outb
*/
static void
bdm_outb (int port, int value)
{
outb (port, value);
}
#undef outb
#define outb(value, port) bdm_outb (port, value)
/*
************************************************************************
* Mappings to OpenBSD *
************************************************************************
*/
#define PRINTF printf
#define udelay(x) DELAY (x)
#define MINOR(x) minor (x)
#define HZ hz
/*
************************************************************************
* Include the driver code *
************************************************************************
*/
#include "../bdm.c"
/*
************************************************************************
* Good old-fashioned UNIX driver entry points *
************************************************************************
*/
static int
openbsd_bdm_open (dev_t dev, int flags, int fmt, struct proc *p)
{
return bdm_open (MINOR (dev));
}
static int
openbsd_bdm_close (dev_t dev, int fflag, int devtype, struct proc *p)
{
return bdm_close (MINOR (dev));
}
static int
openbsd_bdm_read (dev_t dev, struct uio *uio, int flag)
{
return bdm_read (MINOR (dev), (char *)uio, uio->uio_resid);
}
static int
openbsd_bdm_write (dev_t dev, struct uio * uio, int ioflag)
{
return bdm_write (MINOR (dev), (char *)uio, uio->uio_resid);
}
static int
openbsd_bdm_ioctl (dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p)
{
return bdm_ioctl (MINOR (dev), cmd, (unsigned long)arg);
}
/*
* Driver entry points
*/
static int bdm_dev_registered = 0;
void cleanup_module (void);
/*
* Hook driver into kernel
*/
static int
init_module ()
{
int minor;
PRINTF ("bdm_init_module %d.%d, " __DATE__ ", " __TIME__ "\n",
BDM_DRV_VERSION >> 8, BDM_DRV_VERSION & 0xff);
bdm_dev_registered = 1;
/*
* Set up port numbers
*/
for (minor = 0 ;
minor < (sizeof bdm_device_info / sizeof bdm_device_info[0]) ;
minor++) {
int port;
struct BDM *self = &bdm_device_info[minor];
/*
* First set the default debug level.
*/
self->debugFlag = BDM_DEFAULT_DEBUG;
/*
* Choose a port number
*/
switch (BDM_IFACE_MINOR (minor)) {
case 0: port = 0x378; break; /* LPT1 */
case 1: port = 0x278; break; /* LPT2 */
case 2: port = 0x3bc; break; /* LPT3 */
case 3: port = 0x2bc; break; /* LPT4, ccj - made this up :-) */
default:
PRINTF ("BDM driver has no address for LPT%d.\n", BDM_IFACE_MINOR (minor) + 1);
cleanup_module ();
return EIO;
}
/*
* See if the port exists
*/
self->exists = 1;
outb (0x00, port);
bdm_delay (50);
if (inb (port) != 0x00) {
self->exists = 0;
if (self->debugFlag)
PRINTF ("BDM driver cannot detect LPT%d.\n", BDM_IFACE_MINOR (minor) + 1);
continue;
}
sprintf (self->name, "bdm%d", minor);
self->portBase = self->dataPort = port;
self->statusPort = port + 1;
self->controlPort = port + 2;
self->delayTimer = 0;
switch (BDM_IFACE (minor)) {
case BDM_CPU32_PD: cpu32_pd_init_self (self); break;
case BDM_CPU32_ICD: cpu32_icd_init_self (self); break;
case BDM_COLDFIRE_PE: cf_pe_init_self (self); break;
default:
PRINTF ("BDM driver has no interface for minor number\n");
cleanup_module ();
return EIO;
}
}
return 0;
}
/*
* Unhook module from kernel
*/
void
cleanup_module (void)
{
int minor;
for (minor = 0 ;
minor < (sizeof bdm_device_info / sizeof bdm_device_info[0]) ;
minor++) {
struct BDM *self = &bdm_device_info[minor];
if (self->exists && self->portsAreMine)
;
}
if (bdm_dev_registered) {
bdm_dev_registered = 0;
PRINTF ("BDM driver unregistered.\n");
}
}
static struct cdevsw openbsd_devsw =
{
openbsd_bdm_open, /* open */
openbsd_bdm_close, /* close */
openbsd_bdm_read, /* read */
openbsd_bdm_write, /* write */
openbsd_bdm_ioctl, /* ioctl */
(void *)nullop, /* stop */
(void *)NULL, /* tty */
(void *)nullop, /* select */
(void *)nullop, /* mmap */
NULL /* strategy */
};
MOD_DEV("bdm", LM_DT_CHAR, BDM_MAJOR_NUMBER, &openbsd_devsw)
static int
bdmprobe ()
{
/* For now, always report the BDM driver is able to drive the BDM hardware. */
return 0;
}
static int
bdm_load(void)
{
int err;
PRINTF("BDM init_module\n %s\n %s\n %s\n",
"$RCSfile: openbsd-bdm.c,v $", "$Revision: 1.1 $", "$Date: 2004/04/18 16:51:21 $");
PRINTF(" Version %s\n Compiled at %s %s\n",
"PD-interface",
__DATE__, __TIME__);
err = bdmprobe ();
if (err) {
PRINTF ("BDM driver: probe failed\n");
return err;
}
err = init_module();
if (err) {
PRINTF ("BDM driver: load failed\n");
return err;
}
PRINTF ("BDM driver: loaded\n");
return 0;
}
static int
bdm_unload(void)
{
PRINTF ("BDM driver: unloaded\n");
return 0;
}
static int
bdm_handler(struct lkm_table *lkmtp, int cmd)
{
int iStatus = 0;
struct lkm_dev *args = lkmtp->private.lkm_dev;
switch ( cmd ) {
case LKM_E_LOAD:
iStatus = bdm_load();
break;
case LKM_E_UNLOAD:
iStatus = bdm_unload();
break;
}
return ( iStatus );
}
int bdm(struct lkm_table *lkmtp, int cmd, int ver)
{
DISPATCH(lkmtp, cmd, ver, bdm_handler, lkm_nofunc, lkm_nofunc);
}