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
2 changed files with 128 additions and 109 deletions
sys/dev/ppbus

@ -41,10 +41,6 @@
#include <sys/bus.h> #include <sys/bus.h>
#include <sys/malloc.h> #include <sys/malloc.h>
#endif /* _KERNEL */
#ifdef _KERNEL
#endif /* _KERNEL */ #endif /* _KERNEL */
#include "opt_vpo.h" #include "opt_vpo.h"
@ -67,6 +63,24 @@
* Microcode to execute very fast I/O sequences at the lowest bus level. * 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 SELECT_TARGET MS_PARAM(6, 1, MS_TYP_CHA)
#define DECLARE_SELECT_MICROSEQUENCE \ #define DECLARE_SELECT_MICROSEQUENCE \
@ -134,7 +148,7 @@ struct ppb_microseq cpp_microseq[] = { \
#define NEGOCIATED_MODE MS_PARAM(2, 1, MS_TYP_CHA) #define NEGOCIATED_MODE MS_PARAM(2, 1, MS_TYP_CHA)
#define DECLARE_NEGOCIATE_MICROSEQ \ #define DECLARE_NEGOCIATE_MICROSEQ \
static struct ppb_microseq negociate_microseq[] = { \ struct ppb_microseq negociate_microseq[] = { \
MS_CASS(0x4), \ MS_CASS(0x4), \
MS_DELAY(5), \ MS_DELAY(5), \
MS_DASS(MS_UNKNOWN /* mode */), \ MS_DASS(MS_UNKNOWN /* mode */), \
@ -155,6 +169,35 @@ static struct ppb_microseq negociate_microseq[] = { \
MS_RET(0) \ 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[] = { static struct ppb_microseq reset_microseq[] = {
MS_CASS(0x04), MS_CASS(0x04),
MS_DASS(0x40), MS_DASS(0x40),
@ -183,47 +226,6 @@ nibble_inbyte_hook (void *p, char *ptr)
return (0); 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 * 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. * H_SELIN must be low.
* *
* XXX should be ported to microseq
*/ */
static char static char
imm_wait(struct vpoio_data *vpo, int tmo) imm_wait(struct vpoio_data *vpo, int tmo)
{ {
DECLARE_WAIT_MICROSEQUENCE;
device_t ppbus = device_get_parent(vpo->vpo_dev); device_t ppbus = device_get_parent(vpo->vpo_dev);
register int k; int ret, err;
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);
/* /*
* Return some status information. * Return some status information.
@ -506,11 +501,17 @@ imm_wait(struct vpoio_data *vpo, int tmo)
* 0xa8 = ZIP+ wants command * 0xa8 = ZIP+ wants command
* 0xb8 = end of transfer, ZIP+ is sending status * 0xb8 = end of transfer, ZIP+ is sending status
*/ */
ppb_wctr(ppbus, 0x4);
if (k < tmo)
return (r & 0xb8);
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 (0); /* command timed out */
return(ret);
} }
static int static int
@ -574,7 +575,9 @@ imm_probe(device_t dev, struct vpoio_data *vpo)
int int
imm_attach(struct vpoio_data *vpo) imm_attach(struct vpoio_data *vpo)
{ {
DECLARE_NIBBLE_INBYTE_SUBMICROSEQ;
device_t ppbus = device_get_parent(vpo->vpo_dev); device_t ppbus = device_get_parent(vpo->vpo_dev);
int error = 0;
/* /*
* Initialize microsequence code * Initialize microsequence code
@ -589,12 +592,17 @@ imm_attach(struct vpoio_data *vpo)
(void *)vpo->vpo_nibble_inbyte_msq, (void *)vpo->vpo_nibble_inbyte_msq,
sizeof(nibble_inbyte_submicroseq)); 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 * 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 */ /* ppbus automatically restore the last mode entered during detection */
switch (vpo->vpo_mode_found) { switch (vpo->vpo_mode_found) {
@ -618,8 +626,8 @@ imm_attach(struct vpoio_data *vpo)
} }
ppb_release_bus(ppbus, vpo->vpo_dev); ppb_release_bus(ppbus, vpo->vpo_dev);
error:
return (0); return (error);
} }
/* /*
@ -671,7 +679,7 @@ imm_do_scsi(struct vpoio_data *vpo, int host, int target, char *command,
* XXX * XXX
* Should we allow this call to be interruptible? * Should we allow this call to be interruptible?
* The only way to report the interruption is to return * 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))) if ((error = imm_connect(vpo, PPB_WAIT|PPB_INTR, &not_connected, 1)))
return (error); return (error);

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