1.\" Copyright (c) 1998, 1999, Nicolas Souchu 2.\" All rights reserved. 3.\" 4.\" Redistribution and use in source and binary forms, with or without 5.\" modification, are permitted provided that the following conditions 6.\" are met: 7.\" 1. Redistributions of source code must retain the above copyright 8.\" notice, this list of conditions and the following disclaimer. 9.\" 2. Redistributions in binary form must reproduce the above copyright 10.\" notice, this list of conditions and the following disclaimer in the 11.\" documentation and/or other materials provided with the distribution. 12.\" 13.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23.\" SUCH DAMAGE. 24.\" 25.\" $FreeBSD$ 26.\" 27.Dd June 6, 1998 28.Dt MICROSEQ 9 29.Os 30.Sh NAME 31.Nm microseq 32.Nd ppbus microseqencer developer's guide 33.Sh SYNOPSIS 34.Fd "#include <sys/types.h>" 35.Fd "#include <dev/ppbus/ppbconf.h>" 36.Fd "#include <dev/ppbus/ppb_msq.h>" 37.Sh DESCRIPTION 38See 39.Xr ppbus 4 40for ppbus description and general info about the microsequencer. 41.Pp 42The purpose of this document is to encourage developers to use the 43microsequencer mechanism in order to have: 44.Bl -enum -offset indent 45.It 46a uniform programming model 47.It 48efficient code 49.El 50.Pp 51Before using microsequences, you are encouraged to look at 52.Xr ppc 4 53microsequencer implementation and an example of how using it in 54.Xr vpo 4 . 55.Sh PPBUS register model 56.Ss Background 57The parallel port model chosen for ppbus is the PC parallel port model. 58Thus, any register described later has the same semantic than its counterpart 59in a PC parallel port. 60For more info about ISA/ECP programming, get the 61Microsoft standard referenced as "Extended Capabilities Port Protocol and 62ISA interface Standard". Registers described later are standard parallel port 63registers. 64.Pp 65Mask macros are defined in the standard ppbus include files for each valid 66bit of parallel port registers. 67.Ss Data register 68In compatible or nibble mode, writing to this register will drive data to the 69parallel port data lines. 70In any other mode, drivers may be tri-stated by 71setting the direction bit (PCD) in the control register. 72Reads to this register 73return the value on the data lines. 74.Ss Device status register 75This read-only register reflects the inputs on the parallel port interface. 76.Pp 77.Bl -column "Bit" "Name" "Description" -compact 78.It Em Bit Ta Em Name Ta Em Description 79.It 7 Ta nBUSY Ta "inverted version of parallel port Busy signal" 80.It 6 Ta nACK Ta "version of parallel port nAck signal" 81.It 5 Ta PERROR Ta "version of parallel port PERROR signal" 82.It 4 Ta SELECT Ta "version of parallel port Select signal" 83.It 3 Ta nFAULT Ta "version of parallel port nFault signal" 84.El 85.Pp 86Others are reserved and return undefined result when read. 87.Ss Device control register 88This register directly controls several output signals as well as enabling 89some functions. 90.Pp 91.Bl -column "Bit" "Name " "Description" -compact 92.It Em Bit Ta Em Name Ta Em Description 93.It 5 Ta PCD Ta "direction bit in extended modes" 94.It 4 Ta IRQENABLE Ta "1 enables an interrupt on the rising edge of nAck" 95.It 3 Ta SELECTIN Ta "inverted and driven as parallel port nSelectin signal" 96.It 2 Ta nINIT Ta "driven as parallel port nInit signal" 97.It 1 Ta AUTOFEED Ta "inverted and driven as parallel port nAutoFd signal" 98.It 0 Ta STROBE Ta "inverted and driven as parallel port nStrobe signal" 99.El 100.Sh MICROINSTRUCTIONS 101.Ss Description 102.Em Microinstructions 103are either parallel port accesses, program iterations, submicrosequence or 104C calls. 105The parallel port must be considered as the logical model described in 106.Xr ppbus 4 . 107.Pp 108Available microinstructions are: 109.Bd -literal 110#define MS_OP_GET 0 /* get <ptr>, <len> */ 111#define MS_OP_PUT 1 /* put <ptr>, <len> */ 112#define MS_OP_RFETCH 2 /* rfetch <reg>, <mask>, <ptr> */ 113#define MS_OP_RSET 3 /* rset <reg>, <mask>, <mask> */ 114#define MS_OP_RASSERT 4 /* rassert <reg>, <mask> */ 115#define MS_OP_DELAY 5 /* delay <val> */ 116#define MS_OP_SET 6 /* set <val> */ 117#define MS_OP_DBRA 7 /* dbra <offset> */ 118#define MS_OP_BRSET 8 /* brset <mask>, <offset> */ 119#define MS_OP_BRCLEAR 9 /* brclear <mask>, <offset> */ 120#define MS_OP_RET 10 /* ret <retcode> */ 121#define MS_OP_C_CALL 11 /* c_call <function>, <parameter> */ 122#define MS_OP_PTR 12 /* ptr <pointer> */ 123#define MS_OP_ADELAY 13 /* adelay <val> */ 124#define MS_OP_BRSTAT 14 /* brstat <mask>, <mask>, <offset> */ 125#define MS_OP_SUBRET 15 /* subret <code> */ 126#define MS_OP_CALL 16 /* call <microsequence> */ 127#define MS_OP_RASSERT_P 17 /* rassert_p <iter>, <reg> */ 128#define MS_OP_RFETCH_P 18 /* rfetch_p <iter>, <reg>, <mask> */ 129#define MS_OP_TRIG 19 /* trigger <reg>, <len>, <array> */ 130.Ed 131.Ss Execution context 132The 133.Em execution context 134of microinstructions is: 135.Bl -bullet -offset indent 136.It 137the 138.Em program counter 139which points to the next microinstruction to execute either in the main 140microsequence or in a subcall 141.It 142the current value of 143.Em ptr 144which points to the next char to send/receive 145.It 146the current value of the internal 147.Em branch register 148.El 149.Pp 150This data is modified by some of the microinstructions, not all. 151.Ss MS_OP_GET and MS_OP_PUT 152are microinstructions used to do either predefined standard IEEE1284-1994 153transfers or programmed non-standard io. 154.Ss MS_OP_RFETCH - Register FETCH 155is used to retrieve the current value of a parallel port register, apply a 156mask and save it in a buffer. 157.Pp 158Parameters: 159.Bl -enum -offset indent 160.It 161register 162.It 163character mask 164.It 165pointer to the buffer 166.El 167.Pp 168Predefined macro: MS_RFETCH(reg,mask,ptr) 169.Ss MS_OP_RSET - Register SET 170is used to assert/clear some bits of a particular parallel port register, 171two masks are applied. 172.Pp 173Parameters: 174.Bl -enum -offset indent 175.It 176register 177.It 178mask of bits to assert 179.It 180mask of bits to clear 181.El 182.Pp 183Predefined macro: MS_RSET(reg,assert,clear) 184.Ss MS_OP_RASSERT - Register ASSERT 185is used to assert all bits of a particular parallel port register. 186.Pp 187Parameters: 188.Bl -enum -offset indent 189.It 190register 191.It 192byte to assert 193.El 194.Pp 195Predefined macro: MS_RASSERT(reg,byte) 196.Ss MS_OP_DELAY - microsecond DELAY 197is used to delay the execution of the microsequence. 198.Pp 199Parameter: 200.Bl -enum -offset indent 201.It 202delay in microseconds 203.El 204.Pp 205Predefined macro: MS_DELAY(delay) 206.Ss MS_OP_SET - SET internal branch register 207is used to set the value of the internal branch register. 208.Pp 209Parameter: 210.Bl -enum -offset indent 211.It 212integer value 213.El 214.Pp 215Predefined macro: MS_SET(accum) 216.Ss MS_OP_DBRA - \&Do BRAnch 217is used to branch if internal branch register decremented by one result value 218is positive. 219.Pp 220Parameter: 221.Bl -enum -offset indent 222.It 223integer offset in the current executed (sub)microsequence. 224Offset is added to 225the index of the next microinstruction to execute. 226.El 227.Pp 228Predefined macro: MS_DBRA(offset) 229.Ss MS_OP_BRSET - BRanch on SET 230is used to branch if some of the status register bits of the parallel port 231are set. 232.Pp 233Parameter: 234.Bl -enum -offset indent 235.It 236bits of the status register 237.It 238integer offset in the current executed (sub)microsequence. 239Offset is added to 240the index of the next microinstruction to execute. 241.El 242.Pp 243Predefined macro: MS_BRSET(mask,offset) 244.Ss MS_OP_BRCLEAR - BRanch on CLEAR 245is used to branch if some of the status register bits of the parallel port 246are cleared. 247.Pp 248Parameter: 249.Bl -enum -offset indent 250.It 251bits of the status register 252.It 253integer offset in the current executed (sub)microsequence. 254Offset is added to 255the index of the next microinstruction to execute. 256.El 257.Pp 258Predefined macro: MS_BRCLEAR(mask,offset) 259.Ss MS_OP_RET - RETurn 260is used to return from a microsequence. 261This instruction is mandatory. 262This 263is the only way for the microsequencer to detect the end of the microsequence. 264The return code is returned in the integer pointed by the (int *) parameter 265of the ppb_MS_microseq(). 266.Pp 267Parameter: 268.Bl -enum -offset indent 269.It 270integer return code 271.El 272.Pp 273Predefined macro: MS_RET(code) 274.Ss MS_OP_C_CALL - C function CALL 275is used to call C functions from microsequence execution. 276This may be useful 277when a non-standard i/o is performed to retrieve a data character from the 278parallel port. 279.Pp 280Parameter: 281.Bl -enum -offset indent 282.It 283the C function to call 284.It 285the parameter to pass to the function call 286.El 287.Pp 288The C function shall be declared as a 289.Ft int(*)(void *p, char *ptr) . 290The ptr parameter is the current position in the buffer currently scanned. 291.Pp 292Predefined macro: MS_C_CALL(func,param) 293.Ss MS_OP_PTR - initialize internal PTR 294is used to initialize the internal pointer to the currently scanned buffer. 295This pointer is passed to any C call (see above). 296.Pp 297Parameter: 298.Bl -enum -offset indent 299.It 300pointer to the buffer that shall be accessed by xxx_P() microsequence calls. 301Note that this pointer is automatically incremented during xxx_P() calls 302.El 303.Pp 304Predefined macro: MS_PTR(ptr) 305.Ss MS_OP_ADELAY - do an Asynchronous DELAY 306is used to make a tsleep() during microsequence execution. 307The tsleep is 308executed at PPBPRI level. 309.Pp 310Parameter: 311.Bl -enum -offset indent 312.It 313delay in ms 314.El 315.Pp 316Predefined macro: MS_ADELAY(delay) 317.Ss MS_OP_BRSTAT - BRanch on STATe 318is used to branch on status register state condition. 319.Pp 320Parameter: 321.Bl -enum -offset indent 322.It 323mask of asserted bits. 324Bits that shall be asserted in the status register 325are set in the mask 326.It 327mask of cleared bits. 328Bits that shall be cleared in the status register 329are set in the mask 330.It 331integer offset in the current executed (sub)microsequence. 332Offset is added 333to the index of the next microinstruction to execute. 334.El 335.Pp 336Predefined macro: MS_BRSTAT(asserted_bits,clear_bits,offset) 337.Ss MS_OP_SUBRET - SUBmicrosequence RETurn 338is used to return from the submicrosequence call. 339This action is mandatory 340before a RET call. 341Some microinstructions (PUT, GET) may not be callable 342within a submicrosequence. 343.Pp 344No parameter. 345.Pp 346Predefined macro: MS_SUBRET() 347.Ss MS_OP_CALL - submicrosequence CALL 348is used to call a submicrosequence. 349A submicrosequence is a microsequence with 350a SUBRET call. 351Parameter: 352.Bl -enum -offset indent 353.It 354the submicrosequence to execute 355.El 356.Pp 357Predefined macro: MS_CALL(microseq) 358.Ss MS_OP_RASSERT_P - Register ASSERT from internal PTR 359is used to assert a register with data currently pointed by the internal PTR 360pointer. 361Parameter: 362.Bl -enum -offset indent 363.It 364amount of data to write to the register 365.It 366register 367.El 368.Pp 369Predefined macro: MS_RASSERT_P(iter,reg) 370.Ss MS_OP_RFETCH_P - Register FETCH to internal PTR 371is used to fetch data from a register. 372Data is stored in the buffer currently 373pointed by the internal PTR pointer. 374Parameter: 375.Bl -enum -offset indent 376.It 377amount of data to read from the register 378.It 379register 380.It 381mask applied to fetched data 382.El 383.Pp 384Predefined macro: MS_RFETCH_P(iter,reg,mask) 385.Ss MS_OP_TRIG - TRIG register 386is used to trigger the parallel port. 387This microinstruction is intended to 388provide a very efficient control of the parallel port. 389Triggering a register 390is writing data, wait a while, write data, wait a while... 391This allows to 392write magic sequences to the port. 393Parameter: 394.Bl -enum -offset indent 395.It 396amount of data to read from the register 397.It 398register 399.It 400size of the array 401.It 402array of unsigned chars. 403Each couple of u_chars define the data to write to 404the register and the delay in us to wait. 405The delay is limited to 255 us to 406simplify and reduce the size of the array. 407.El 408.Pp 409Predefined macro: MS_TRIG(reg,len,array) 410.Sh MICROSEQUENCES 411.Ss C structures 412.Bd -literal 413union ppb_insarg { 414 int i; 415 char c; 416 void *p; 417 int (* f)(void *, char *); 418}; 419 420struct ppb_microseq { 421 int opcode; /* microins. opcode */ 422 union ppb_insarg arg[PPB_MS_MAXARGS]; /* arguments */ 423}; 424.Ed 425.Ss Using microsequences 426To instantiate a microsequence, just declare an array of ppb_microseq 427structures and initialize it as needed. 428You may either use predefined macros 429or code directly your microinstructions according to the ppb_microseq 430definition. 431For example, 432.Bd -literal 433 struct ppb_microseq select_microseq[] = { 434 435 /* parameter list 436 */ 437 #define SELECT_TARGET MS_PARAM(0, 1, MS_TYP_INT) 438 #define SELECT_INITIATOR MS_PARAM(3, 1, MS_TYP_INT) 439 440 /* send the select command to the drive */ 441 MS_DASS(MS_UNKNOWN), 442 MS_CASS(H_nAUTO | H_nSELIN | H_INIT | H_STROBE), 443 MS_CASS( H_AUTO | H_nSELIN | H_INIT | H_STROBE), 444 MS_DASS(MS_UNKNOWN), 445 MS_CASS( H_AUTO | H_nSELIN | H_nINIT | H_STROBE), 446 447 /* now, wait until the drive is ready */ 448 MS_SET(VP0_SELTMO), 449/* loop: */ MS_BRSET(H_ACK, 2 /* ready */), 450 MS_DBRA(-2 /* loop */), 451/* error: */ MS_RET(1), 452/* ready: */ MS_RET(0) 453 }; 454.Ed 455.Pp 456Here, some parameters are undefined and must be filled before executing 457the microsequence. 458In order to initialize each microsequence, one 459should use the ppb_MS_init_msq() function like this: 460.Bd -literal 461 ppb_MS_init_msq(select_microseq, 2, 462 SELECT_TARGET, 1 << target, 463 SELECT_INITIATOR, 1 << initiator); 464.Ed 465.Pp 466and then execute the microsequence. 467.Ss The microsequencer 468The microsequencer is executed either at ppbus or adapter level (see 469.Xr ppbus 4 470for info about ppbus system layers). Most of the microsequencer is executed 471at ppc level to avoid ppbus to adapter function call overhead. 472But some 473actions like deciding whereas the transfer is IEEE1284-1994 compliant are 474executed at ppbus layer. 475.Sh BUGS 476Only one level of submicrosequences is allowed. 477.Pp 478When triggering the port, maximum delay allowed is 255 us. 479.Sh SEE ALSO 480.Xr ppbus 4 , 481.Xr ppc 4 , 482.Xr vpo 4 483.Sh HISTORY 484The 485.Nm 486manual page first appeared in 487.Fx 3.0 . 488.Sh AUTHORS 489This 490manual page was written by 491.An Nicolas Souchu . 492