1
0
mirror of https://git.FreeBSD.org/src.git synced 2025-01-25 16:13:17 +00:00

Translate various ppbus sequences into microsequences to limit

overhead of abstraction layers.

Submitted by:	jcm@FreeBSD-uk.eu.org
This commit is contained in:
Nicolas Souchu 2001-06-23 06:51:52 +00:00
parent cd01c79119
commit 334a17f09a
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=78645
2 changed files with 128 additions and 109 deletions

View File

@ -41,12 +41,8 @@
#include <sys/bus.h>
#include <sys/malloc.h>
#endif /* _KERNEL */
#ifdef _KERNEL
#endif /* _KERNEL */
#include "opt_vpo.h"
#include <dev/ppbus/ppbio.h>
@ -67,9 +63,27 @@
* Microcode to execute very fast I/O sequences at the lowest bus level.
*/
#define WAIT_RET MS_PARAM(7, 2, MS_TYP_PTR)
#define WAIT_TMO MS_PARAM(1, 0, MS_TYP_INT)
#define DECLARE_WAIT_MICROSEQUENCE \
struct ppb_microseq wait_microseq[] = { \
MS_CASS(0x0c), \
MS_SET(MS_UNKNOWN), \
/* loop */ \
MS_BRSET(nBUSY, 4 /* ready */), \
MS_DBRA(-2 /* loop */), \
MS_CASS(0x04), \
MS_RET(1), /* timed out */ \
/* ready */ \
MS_CASS(0x04), \
MS_RFETCH(MS_REG_STR, 0xb8, MS_UNKNOWN ), \
MS_RET(0) /* no error */ \
}
#define SELECT_TARGET MS_PARAM(6, 1, MS_TYP_CHA)
#define DECLARE_SELECT_MICROSEQUENCE \
#define DECLARE_SELECT_MICROSEQUENCE \
struct ppb_microseq select_microseq[] = { \
MS_CASS(0xc), \
/* first, check there is nothing holding onto the bus */ \
@ -134,7 +148,7 @@ struct ppb_microseq cpp_microseq[] = { \
#define NEGOCIATED_MODE MS_PARAM(2, 1, MS_TYP_CHA)
#define DECLARE_NEGOCIATE_MICROSEQ \
static struct ppb_microseq negociate_microseq[] = { \
struct ppb_microseq negociate_microseq[] = { \
MS_CASS(0x4), \
MS_DELAY(5), \
MS_DASS(MS_UNKNOWN /* mode */), \
@ -155,6 +169,35 @@ static struct ppb_microseq negociate_microseq[] = { \
MS_RET(0) \
}
#define INB_NIBBLE_L MS_PARAM(3, 2, MS_TYP_PTR)
#define INB_NIBBLE_H MS_PARAM(6, 2, MS_TYP_PTR)
#define INB_NIBBLE_F MS_PARAM(9, 0, MS_TYP_FUN)
#define INB_NIBBLE_P MS_PARAM(9, 1, MS_TYP_PTR)
/*
* This is the sub-microseqence for MS_GET in NIBBLE mode
* Retrieve the two nibbles and call the C function to generate the character
* and store it in the buffer (see nibble_inbyte_hook())
*/
#define DECLARE_NIBBLE_INBYTE_SUBMICROSEQ \
struct ppb_microseq nibble_inbyte_submicroseq[] = { \
MS_CASS(0x4), \
/* loop: */ \
MS_CASS(0x6), \
MS_DELAY(1), \
MS_RFETCH(MS_REG_STR, MS_FETCH_ALL, MS_UNKNOWN /* low nibble */),\
MS_CASS(0x5), \
MS_DELAY(1), \
MS_RFETCH(MS_REG_STR, MS_FETCH_ALL, MS_UNKNOWN /* high nibble */),\
MS_CASS(0x4), \
MS_DELAY(1), \
/* do a C call to format the received nibbles */ \
MS_C_CALL(MS_UNKNOWN /* C hook */, MS_UNKNOWN /* param */), \
MS_DBRA(-7 /* loop */), \
MS_RET(0) \
}
static struct ppb_microseq reset_microseq[] = {
MS_CASS(0x04),
MS_DASS(0x40),
@ -183,47 +226,6 @@ nibble_inbyte_hook (void *p, char *ptr)
return (0);
}
/*
* Macro used to initialize each vpoio_data structure during
* low level attachment
*
* XXX should be converted to ppb_MS_init_msq()
*/
#define INIT_NIBBLE_INBYTE_SUBMICROSEQ(vpo) { \
(vpo)->vpo_nibble_inbyte_msq[6].arg[2].p = \
(void *)&(vpo)->vpo_nibble.h; \
(vpo)->vpo_nibble_inbyte_msq[3].arg[2].p = \
(void *)&(vpo)->vpo_nibble.l; \
(vpo)->vpo_nibble_inbyte_msq[9].arg[0].f = \
nibble_inbyte_hook; \
(vpo)->vpo_nibble_inbyte_msq[9].arg[1].p = \
(void *)&(vpo)->vpo_nibble; \
}
/*
* This is the sub-microseqence for MS_GET in NIBBLE mode
* Retrieve the two nibbles and call the C function to generate the character
* and store it in the buffer (see nibble_inbyte_hook())
*/
static struct ppb_microseq nibble_inbyte_submicroseq[] = {
MS_CASS(0x4),
/* loop: */
MS_CASS(0x6),
MS_DELAY(1),
MS_RFETCH(MS_REG_STR, MS_FETCH_ALL, MS_UNKNOWN /* low nibble */),
MS_CASS(0x5),
MS_DELAY(1),
MS_RFETCH(MS_REG_STR, MS_FETCH_ALL, MS_UNKNOWN /* high nibble */),
MS_CASS(0x4),
MS_DELAY(1),
/* do a C call to format the received nibbles */
MS_C_CALL(MS_UNKNOWN /* C hook */, MS_UNKNOWN /* param */),
MS_DBRA(-7 /* loop */),
MS_RET(0)
};
/*
* This is the sub-microseqence for MS_GET in PS2 mode
*/
@ -483,21 +485,14 @@ imm_select(struct vpoio_data *vpo, int initiator, int target)
*
* H_SELIN must be low.
*
* XXX should be ported to microseq
*/
static char
imm_wait(struct vpoio_data *vpo, int tmo)
{
DECLARE_WAIT_MICROSEQUENCE;
device_t ppbus = device_get_parent(vpo->vpo_dev);
register int k;
register char r;
ppb_wctr(ppbus, 0xc);
/* XXX should be ported to microseq */
k = 0;
while (!((r = ppb_rstr(ppbus)) & 0x80) && (k++ < tmo))
DELAY(1);
int ret, err;
/*
* Return some status information.
@ -506,11 +501,17 @@ imm_wait(struct vpoio_data *vpo, int tmo)
* 0xa8 = ZIP+ wants command
* 0xb8 = end of transfer, ZIP+ is sending status
*/
ppb_wctr(ppbus, 0x4);
if (k < tmo)
return (r & 0xb8);
return (0); /* command timed out */
ppb_MS_init_msq(wait_microseq, 2,
WAIT_RET, (void *)&ret,
WAIT_TMO, tmo);
ppb_MS_microseq(ppbus, vpo->vpo_dev, wait_microseq, &err);
if (err)
return (0); /* command timed out */
return(ret);
}
static int
@ -574,7 +575,9 @@ imm_probe(device_t dev, struct vpoio_data *vpo)
int
imm_attach(struct vpoio_data *vpo)
{
DECLARE_NIBBLE_INBYTE_SUBMICROSEQ;
device_t ppbus = device_get_parent(vpo->vpo_dev);
int error = 0;
/*
* Initialize microsequence code
@ -589,12 +592,17 @@ imm_attach(struct vpoio_data *vpo)
(void *)vpo->vpo_nibble_inbyte_msq,
sizeof(nibble_inbyte_submicroseq));
INIT_NIBBLE_INBYTE_SUBMICROSEQ(vpo);
ppb_MS_init_msq(vpo->vpo_nibble_inbyte_msq, 4,
INB_NIBBLE_H, (void *)&(vpo)->vpo_nibble.h,
INB_NIBBLE_L, (void *)&(vpo)->vpo_nibble.l,
INB_NIBBLE_F, nibble_inbyte_hook,
INB_NIBBLE_P, (void *)&(vpo)->vpo_nibble);
/*
* Initialize mode dependent in/out microsequences
*/
ppb_request_bus(ppbus, vpo->vpo_dev, PPB_WAIT);
if ((error = ppb_request_bus(ppbus, vpo->vpo_dev, PPB_WAIT)))
goto error;
/* ppbus automatically restore the last mode entered during detection */
switch (vpo->vpo_mode_found) {
@ -618,8 +626,8 @@ imm_attach(struct vpoio_data *vpo)
}
ppb_release_bus(ppbus, vpo->vpo_dev);
return (0);
error:
return (error);
}
/*
@ -671,7 +679,7 @@ imm_do_scsi(struct vpoio_data *vpo, int host, int target, char *command,
* XXX
* Should we allow this call to be interruptible?
* The only way to report the interruption is to return
* EIO do upper SCSI code :^(
* EIO to upper SCSI code :^(
*/
if ((error = imm_connect(vpo, PPB_WAIT|PPB_INTR, &not_connected, 1)))
return (error);

View File

@ -35,6 +35,7 @@
#include <sys/bus.h>
#include <sys/malloc.h>
#include <machine/clock.h>
#endif
@ -97,6 +98,21 @@
* Microcode to execute very fast I/O sequences at the lowest bus level.
*/
#define WAIT_RET MS_PARAM(4, 2, MS_TYP_PTR)
#define WAIT_TMO MS_PARAM(0, 0, MS_TYP_INT)
#define DECLARE_WAIT_MICROSEQUENCE \
struct ppb_microseq wait_microseq[] = { \
MS_SET(MS_UNKNOWN), \
/* loop */ \
MS_BRSET(nBUSY, 2 /* ready */), \
MS_DBRA(-2 /* loop */), \
MS_RET(1), /* timed out */ \
/* ready */ \
MS_RFETCH(MS_REG_STR, 0xf0, MS_UNKNOWN), \
MS_RET(0) /* no error */ \
}
/* call this macro to initialize connect/disconnect microsequences */
#define INIT_TRIG_MICROSEQ { \
int i; \
@ -156,44 +172,31 @@ nibble_inbyte_hook (void *p, char *ptr)
return (0);
}
/*
* Macro used to initialize each vpoio_data structure during
* low level attachment
*
* XXX should be converted to ppb_MS_init_msq()
*/
#define INIT_NIBBLE_INBYTE_SUBMICROSEQ(vpo) { \
(vpo)->vpo_nibble_inbyte_msq[2].arg[2].p = \
(void *)&(vpo)->vpo_nibble.h; \
(vpo)->vpo_nibble_inbyte_msq[4].arg[2].p = \
(void *)&(vpo)->vpo_nibble.l; \
(vpo)->vpo_nibble_inbyte_msq[5].arg[0].f = \
nibble_inbyte_hook; \
(vpo)->vpo_nibble_inbyte_msq[5].arg[1].p = \
(void *)&(vpo)->vpo_nibble; \
}
#define INB_NIBBLE_H MS_PARAM(2, 2, MS_TYP_PTR)
#define INB_NIBBLE_L MS_PARAM(4, 2, MS_TYP_PTR)
#define INB_NIBBLE_F MS_PARAM(5, 0, MS_TYP_FUN)
#define INB_NIBBLE_P MS_PARAM(5, 1, MS_TYP_PTR)
/*
* This is the sub-microseqence for MS_GET in NIBBLE mode
* Retrieve the two nibbles and call the C function to generate the character
* and store it in the buffer (see nibble_inbyte_hook())
*/
static struct ppb_microseq nibble_inbyte_submicroseq[] = {
/* loop: */
MS_CASS( H_AUTO | H_SELIN | H_INIT | H_STROBE),
MS_DELAY(VP0_PULSE),
MS_RFETCH(MS_REG_STR, MS_FETCH_ALL, MS_UNKNOWN /* high nibble */),
MS_CASS(H_nAUTO | H_SELIN | H_INIT | H_STROBE),
MS_RFETCH(MS_REG_STR, MS_FETCH_ALL, MS_UNKNOWN /* low nibble */),
/* do a C call to format the received nibbles */
MS_C_CALL(MS_UNKNOWN /* C hook */, MS_UNKNOWN /* param */),
MS_DBRA(-7 /* loop */),
MS_CASS(H_AUTO | H_nSELIN | H_INIT | H_STROBE),
MS_RET(0)
};
#define DECLARE_NIBBLE_INBYTE_SUBMICROSEQ \
struct ppb_microseq nibble_inbyte_submicroseq[] = { \
/* loop: */ \
MS_CASS( H_AUTO | H_SELIN | H_INIT | H_STROBE), \
MS_DELAY(VP0_PULSE), \
MS_RFETCH(MS_REG_STR, MS_FETCH_ALL, MS_UNKNOWN /* high nibble */),\
MS_CASS(H_nAUTO | H_SELIN | H_INIT | H_STROBE), \
MS_RFETCH(MS_REG_STR, MS_FETCH_ALL, MS_UNKNOWN /* low nibble */),\
/* do a C call to format the received nibbles */ \
MS_C_CALL(MS_UNKNOWN /* C hook */, MS_UNKNOWN /* param */),\
MS_DBRA(-7 /* loop */), \
MS_CASS(H_AUTO | H_nSELIN | H_INIT | H_STROBE), \
MS_RET(0) \
}
/*
* This is the sub-microseqence for MS_GET in PS2 mode
@ -364,8 +367,8 @@ vpoio_detect(struct vpoio_data *vpo)
if ((error = ppb_request_bus(ppbus, vpo->vpo_dev, PPB_DONTWAIT)))
return (error);
ppb_MS_microseq(ppbus, vpo->vpo_dev, disconnect_microseq, &ret);
/* Force disconnection */
ppb_MS_microseq(ppbus, vpo->vpo_dev, disconnect_microseq, &ret);
/* Try to enter EPP mode, then connect to the drive in EPP mode */
if (ppb_set_mode(ppbus, PPB_EPP) != -1) {
@ -517,9 +520,10 @@ vpoio_select(struct vpoio_data *vpo, int initiator, int target)
static char
vpoio_wait(struct vpoio_data *vpo, int tmo)
{
DECLARE_WAIT_MICROSEQUENCE;
device_t ppbus = device_get_parent(vpo->vpo_dev);
register int k;
register char r;
int ret, err;
#if 0 /* broken */
if (ppb_poll_device(ppbus, 150, nBUSY, nBUSY, PPB_INTR))
@ -528,11 +532,6 @@ vpoio_wait(struct vpoio_data *vpo, int tmo)
return (ppb_rstr(ppbus) & 0xf0);
#endif
/* XXX should be ported to microseq */
k = 0;
while (!((r = ppb_rstr(ppbus)) & nBUSY) && (k++ < tmo))
;
/*
* Return some status information.
* Semantics : 0xc0 = ZIP wants more data
@ -540,10 +539,17 @@ vpoio_wait(struct vpoio_data *vpo, int tmo)
* 0xe0 = ZIP wants command
* 0xf0 = end of transfer, ZIP is sending status
*/
if (k < tmo)
return (r & 0xf0);
return (0); /* command timed out */
ppb_MS_init_msq(wait_microseq, 2,
WAIT_RET, (void *)&ret,
WAIT_TMO, tmo);
ppb_MS_microseq(ppbus, vpo->vpo_dev, wait_microseq, &err);
if (err)
return (0); /* command timed out */
return(ret);
}
/*
@ -582,6 +588,7 @@ vpoio_probe(device_t dev, struct vpoio_data *vpo)
int
vpoio_attach(struct vpoio_data *vpo)
{
DECLARE_NIBBLE_INBYTE_SUBMICROSEQ;
device_t ppbus = device_get_parent(vpo->vpo_dev);
int error = 0;
@ -595,7 +602,11 @@ vpoio_attach(struct vpoio_data *vpo)
(void *)vpo->vpo_nibble_inbyte_msq,
sizeof(nibble_inbyte_submicroseq));
INIT_NIBBLE_INBYTE_SUBMICROSEQ(vpo);
ppb_MS_init_msq(vpo->vpo_nibble_inbyte_msq, 4,
INB_NIBBLE_H, (void *)&(vpo)->vpo_nibble.h,
INB_NIBBLE_L, (void *)&(vpo)->vpo_nibble.l,
INB_NIBBLE_F, nibble_inbyte_hook,
INB_NIBBLE_P, (void *)&(vpo)->vpo_nibble);
/*
* Initialize mode dependent in/out microsequences