! %TITLE 'SS Device Driver Tables' MODULE sstables (MAIN = ss_unit_init, IDENT = 'V04-01' ! File: SSTABLES.BLI ) = BEGIN !++ ! ! FACILITY: VAX/VMS Executive, I/O Drivers ! ! ABSTRACT: This module contains the driver tables needed by the SS driver. ! ! ENVIRONMENT: Kernel Mode, Non-paged ! ! AUTHOR: James A. Gray ! ! CREATED: 30 October 1984 ! ! MODIFICATION ! HISTORY: ! ! V01.0 James A. Gray, 30 October 1984 ! Original. ! ! V04-001 Michael S. Jordan, 5 January 1987 ! Modified driver tables to make device available by default, ! which is a driver convention as of V4.0. ! !-- %SBTTL 'Declarations' !+ ! SWITCHES: !- SWITCHES ADDRESSING_MODE (EXTERNAL = GENERAL, NONEXTERNAL = WORD_RELATIVE); !+ ! LINKAGES: !- ! None. !+ ! TABLE OF CONTENTS: !- ! None. !+ ! INCLUDE FILES: ! !- LIBRARY 'SYS$LIBRARY:LIB'; ! VMS Interface Definitions. LIBRARY 'USR_LIBRARY:LIBEXT'; ! LIB library extensions. LIBRARY 'USR_LIBRARY:DRIVER'; ! Device driver extensions. REQUIRE 'SSDEF'; ! SS driver definitions. !+ ! MACROS: !- %SBTTL '_DDTAB' UNDECLARE %QUOTE _ddtab; !+ ! FUNCTIONAL DESCRIPTION: ! This macro generates a driver-dispatch table labeled devnam$DDT. ! ! INPUTS: ! devnam Generic name of the device. ! ! start Address of the start-I/O routine. 0 => IOC$RETURN. ! ! unsolic Address of the unsolicited-interrupt-servicing routine. 0 => IOC$RETURN. ! ! functb Address of the function-decision table. ! ! cancel Address of the cancel-I/O routine. 0 => IOC$RETURN. ! ! regdmp Address of the register-dumping routine. 0 => IOC$RETURN. ! ! diagbf Length, in bytes, of the diagnostic buffer. ! ! erlgbf Length, in bytes, of the error-logging buffer. ! ! unitinit Address of the unit-initialization routine. 0 => IOC$RETURN. ! ! altstart Address of the alternate start-I/O routine. 0 => IOC$RETURN. ! ! mntver Address of the mount-verification routine; the default is suitable ! for all single-stream disk drives. ! ! cloneducb Address of the routine called when a UCB is cloned by the $ASSIGN ! system service. 0 => IOC$RETURN. ! ! mntv_sssc 0 => IOC$RETURN. ! ! mntv_for 0 => IOC$RETURN. ! ! mntv_sqd 0 => IOC$RETURN. ! ! aux_storage Address of auxiliary storage area. ! ! aux_routine Address of auxiliary routine. ! ! legal List of legal I/O function codes without the leading IO$_. ! ! buffered List of buffered I/O function codes without the leading IO$_. ! ! actions Action/function code list tuple for each FDT action to be taken. ! ! VALUE: ! !- KEYWORDMACRO _ddtab ( devnam, start = 0, unsolic = 0, functb, cancel = 0, regdmp = 0, diagbf = 0, erlgbf = 0, unitinit = 0, altstart = 0, mntver = ioc$mntver, cloneducb = 0, mntv_sssc = 0, mntv_for = 0, mntv_sqd = 0, aux_storage = 0, aux_routine = 0, legal = 0, buffered = 0, actions) = !+ ! FUNCTIONAL DESCRIPTION: ! Used to count the number of tuples passed as a single argument. ! ! INPUTS: ! tuple_size The size (in arguments) of each tuple to follow. ! ! %REMAINING The tuples to be counted. ! ! EXPANSION: ! The number of tuples of specified size (in arguments). Partial tuples are ! not counted. !- MACRO __tuple_count (tuple_size) = (%LENGTH - 1) %QUOTE %; !+ ! FUNCTIONAL DESCRIPTION: ! This macro generates an entry for a function descision table. ! ! INPUTS: ! action Routine to call when the function code specified in the I/O request ! matches the code argument to this macro; if this is to be the first or ! second entry in the table, this argument must not be supplied. ! ! codes Code or codes for which the routine specified in the first argument ! to this macro is to be called; the codes are specified as the I/O-function ! codes of the form, IO$_xxx, but without the IO$_ prefix; if more than one ! code is specified then they must be enclosed within angle brackets (<>). ! ! EXPANSION: ! !- MACRO __functab (action, codes) = OWN functable : ALIGN (0) BITVECTOR [64] PSECT ($$$115_driver) PRESET (__setbit (%REMOVE ( codes))); %IF NOT %NULL (action) %THEN OWN actaddr : ALIGN (0) PSECT ($$$115_driver) INITIAL (_genraddr (action, actaddr + 8)); UNDECLARE actaddr; %FI UNDECLARE functable; %QUOTE %; MACRO __functable [tuple] = __functab (%REMOVE (tuple)) %QUOTE %; MACRO __genraddr (address) = _genraddr (address, %NAME (devnam, '$DDT')) %QUOTE %; MACRO __setbit [CODE] = [%quotename ('IO$_', CODE)] = 1 %QUOTE %; %IF %IDENTICAL (mntver, ioc$mntver) %THEN %IF NOT %DECLARED (ioc$mntver) %THEN EXTERNAL ROUTINE ioc$mntver : ADDRESSING_MODE (GENERAL); %FI %FI FORWARD functb : VECTOR [0, BYTE] PSECT ($$$115_driver); GLOBAL %NAME (devnam, '$DDT') : BLOCK [ddt$k_length, BYTE] PSECT ($$$115_driver) ! PRESET ( ! [ddt$l_start] = __genraddr (start), ! Address of driver start I/O routine [ddt$l_unsolint] = __genraddr (unsolic), ! Address of unsolicited interrupt routine [ddt$l_fdt] = __genraddr (functb), ! Address of function decision table [ddt$l_cancel] = __genraddr (cancel), ! Address of cancel I/O entry point [ddt$l_regdump] = __genraddr (regdmp), ! Address of device register dump routine [ddt$w_diagbuf] = diagbf, ! Size of diagnostic buffer in bytes [ddt$w_errorbuf] = erlgbf, ! Size of error log buffer in bytes [ddt$l_unitinit] = __genraddr (unitinit), ! Unit initialization entry point [ddt$l_altstart] = __genraddr (altstart), ! Alternate start I/O entry point [ddt$l_mntver] = __genraddr (mntver), ! Address of mount verification routine [ddt$w_fdtsize] = 16 + (__tuple_count (2, %REMOVE (actions))*12), ! Size of FDT in bytes [ddt$l_cloneducb] = __genraddr (cloneducb), ! Address of cloned UCB entry point [ddt$l_mntv_sssc] = __genraddr (mntv_sssc), ! Address of shadow set state change MV entry [ddt$l_mntv_for] = __genraddr (mntv_for), ! Address of foreign device MV entry [ddt$l_mntv_sqd] = __genraddr (mntv_sqd), ! Address of sequential device MV entry [ddt$l_aux_storage] = __genraddr (aux_storage), ! Address of auxiliary storage area [ddt$l_aux_routine] = __genraddr (aux_routine) ! Address of auxiliary routine ); OWN functb : ALIGN (0) VECTOR [0, BYTE] PSECT ($$$115_driver); __functab (, legal); __functab (, buffered); __functable (%REMOVE (actions)); UNDECLARE %QUOTE %QUOTE __genraddr, %QUOTE %QUOTE __tuple_count, %QUOTE %QUOTE __setbit; %; %SBTTL '_DPTAB' UNDECLARE %QUOTE _dptab; !+ ! FUNCTIONAL DESCRIPTION: ! This macro generates a driver-prologue table in a program section called $$$105_PROLOGUE. ! ! INPUTS: ! devnam Generic name of the device. ! ! adapter Type of adapter, e.g. UBA, MBA, DR, NULL. ! ! flags Flags used in loading the driver. ! ! ucbsize Size, in bytes, of the unit-control block required by each ! device that this driver will drive. ! ! unload Address of the routine in the driver that SYSGEN is to call ! before unloading the driver and loading a new version of the driver. ! ! maxunits Maximum number of device units that can be connected to the ! controller. ! ! defunits Maximum number of UCBs to be created by SYSGEN's AUTOCONFIGURE ! command (one for each device unit to be configured). ! ! deliver Address of the routine in the driver that determines whether a ! unit should be configured automatically, the unit-delivery routine. ! ! vec Reserved to DIGITAL; the address of a driver-specific transfer vector. ! ! name Name of the device driver. ! ! dpt_psect ! ! smp ! ! decode ! ! VALUE: ! !- KEYWORDMACRO _dptab ( devnam, adapter, flags = 0, ucbsize, unload, maxunits = 8, defunits = 1, deliver, vec, name, dpt_psect = $$$105_prologue, smp = no, decode) = MACRO __ascic (fld_off, fld_pos, fld_siz, fld_ext, str_siz, str_text) = %IF fld_pos NEQ 0 %THEN %ERROR ('String does not begin on a BYTE boundary') %FI %IF str_siz LSS (1 + %CHARCOUNT (str_text)) %THEN %ERROR ('Insufficient space for string') %FI [fld_off, 0, 8, 0] = %CHARCOUNT (str_text), __ascii (fld_off + 1, %EXPLODE (str_text)) %QUOTE %; MACRO __ascii (fld_off) [character] = [fld_off + %COUNT, 0, 8, 0] = character %QUOTE %; MACRO __reladdr (address) = %IF NOT %NULL (address) %THEN address - dpt_tab %ELSE 0 %FI %QUOTE %; MACRO __zero (fld_off, fld_pos, fld_siz, fld_ext, siz) [] = %IF fld_pos NEQ 0 %THEN %ERROR ('Field does not begin on a BYTE boundary') %FI [fld_off + %COUNT, 0, 8, 0] = 0 %IF (%COUNT + 1) LSSU siz %THEN , __zero (fld_off, fld_pos, fld_siz, fld_ext, siz) %FI %QUOTE %; FORWARD dpt_initab : VECTOR [0, BYTE] PSECT (dpt_psect), dpt_reinitab : VECTOR [0, BYTE] PSECT (dpt_psect); OWN %NAME (devnam, '_B_END') : VECTOR [0, BYTE] PSECT ($$$125_epilogue); OWN dpt_tab : BLOCK [dpt$k_length, BYTE] PSECT (dpt_psect) ! PRESET ( ! [dpt$w_size] = %NAME (devnam, '_B_END') - dpt_tab, ! Size of driver [dpt$b_type] = dyn$c_dpt, ! Structure type [dpt$b_refc] = 0, ! Count of DDB's that reference driver [dpt$b_adptype] = %NAME ('AT$_', adapter), ! Adapter type code [dpt$w_ucbsize] = ucbsize, ! Size of UCB [dpt$l_flags] = flags OR ! Driver loader flags %IF %IDENTICAL (smp, yes) %THEN dpt$m_smpmod %ELSE 0 %FI , [dpt$w_inittab] = dpt_initab - dpt_tab, ! Offset to init table [dpt$w_reinittab] = dpt_reinitab - dpt_tab, ! Offset to re-init table [dpt$w_unload] = __reladdr (unload), ! Offset to unload action routine [dpt$w_maxunits] = maxunits, ! Maximum units that can be connected [dpt$w_version] = dpt$c_version, ! Driver prologue version number [dpt$w_defunits] = defunits, ! Default number of units [dpt$w_deliver] = __reladdr (deliver), ! Offset to driver unit delivery routine [dpt$w_vector] = __reladdr (vec), ! Offset to vector table (in TTDRIVER) __ascic (dpt$t_name, dpt$s_name, name), ! Driver name (counted string) %IF 0 %THEN __zero (dpt$q_linktime, dpt$s_linktime), ! Link date and time from image header [dpt$l_ecolevel] = 0 ! ECO level from image header __zero(dpt$q_lmf1, dpt$s_lmf1), ! Reserved space for LMF __zero (dpt$q_lmf2, dpt$s_lmf2), ! Reserved space for LMF __zero (dpt$q_lmf3, dpt$s_lmf3), ! Reserved space for LMF __zero (dpt$q_lmf4, dpt$s_lmf4), ! Reserved space for LMF __zero (dpt$q_lmf5, dpt$s_lmf5), ! Reserved space for LMF __zero (dpt$q_lmf6, dpt$s_lmf6), ! Reserved space for LMF __zero (dpt$q_lmf7, dpt$s_lmf7), ! Reserved space for LMF __zero (dpt$q_lmf8, dpt$s_lmf8), ! Reserved space for LMF %FI [dpt$w_decw_sname] = __reladdr (decode) ! Offset to counted ASCII string ); UNDECLARE %QUOTE %QUOTE __ascic, %QUOTE %QUOTE __reladdr; %; %SBTTL '_DPT_STORE' UNDECLARE %QUOTE _dpt_store; !+ ! FUNCTIONAL DESCRIPTION: ! This macro, used within a driver, instructs the system's driver-loading procedure to store ! values in a table of data structure. ! ! INPUTS: ! str_type The type of control block into which the data is to be stored (DDB, ! UCB, ORB, CRB or IDB) or a table marker (INIT, REINIT or END). ! ! str_off The offset, in bytes, from the begining of the data structure at ! which the data is to be stored. ! ! str_pos The offset, in bits, from the position specified by STR_OFF at ! which the data is to be stored. Not used; only present so field ! macros may be used. ! ! str_siz The size, in bits, of the field at which the data is to be stored. ! Only used if OPER='V'. ! ! str_ext The sign extension flag of the field at which the data is to be ! stored. Only used if OPER='V'. ! ! oper The type of storage operation, one of the following: ! 'B' Byte ! 'W' Word ! 'L' Longword ! 'D' Address relative to the begining of the driver ! 'V' Bit field ! If an at-sign character (@) precedes the OPER argument, then the ! EXP argument describes the address of the data with which to ! initialize the field, e.g. '@B'. ! ! exp The value with which to initialize the field; if OPER is preceded ! by an at-sign (@), then the address at which to find the value ! with which to initialize the field. ! ! VALUE: ! !- MACRO _dpt_store (str_type, str_off, str_pos, str_siz, str_ext, oper, exp) = %IF %IDENTICAL (str_type, 'INIT') %THEN OWN dpt_initab : ALIGN (0) VECTOR [0, BYTE] PSECT ($$$105_prologue); %ELSE %IF %IDENTICAL (str_type, 'REINIT') %THEN OWN dpt_reinitab : ALIGN (0) VECTOR [0, BYTE] PSECT ($$$105_prologue); %ELSE %IF %IDENTICAL (str_type, 'END') %THEN OWN dpt : ALIGN (0)BYTE PSECT ($$$105_prologue) INITIAL (BYTE (0)); UNDECLARE dpt; %ELSE MACRO __byte = 0, 8, 0 %QUOTE %; MACRO __word = 0, 16, 0 %QUOTE %; MACRO __long = 0, 32, 0 %QUOTE %; MACRO __convert_op (char) [] = %IF %IDENTICAL (char, '@') %THEN %ASSIGN ($$op, %X'80') %ELSE %IF %IDENTICAL (char, 'W') %THEN %ASSIGN ($$op, $$op OR 1) %ELSE %IF %IDENTICAL (char, 'D') %THEN %ASSIGN ($$op, $$op OR 2) %ELSE %IF %IDENTICAL (char, 'L') %THEN %ASSIGN ($$op, $$op OR 3) %ELSE %IF %IDENTICAL (char, 'V') %THEN %ASSIGN ($$op, $$op OR 4) %FI %FI %FI %FI %FI %QUOTE __convert_op (%REMAINING) %QUOTE %; COMPILETIME $$op = 0; __convert_op (oper); %IF str_off LSSU 255 %THEN OWN dpt : ALIGN (0) VECTOR [2, BYTE] PSECT ($$$105_prologue) ! INITIAL (BYTE (%NAME ('DPT$K_STRUC_', str_type), str_off)); %ELSE OWN dpt : ALIGN (0)BYTE PSECT ($$$105_prologue) ! INITIAL (BYTE (%NAME ('DPT$K_STRUC_', str_type) OR dpt$m_struc_wrd)); UNDECLARE dpt; OWN dpt : ALIGN (0)WORD PSECT ($$$105_prologue) ! INITIAL (WORD (str_off)); %FI UNDECLARE dpt; OWN dpt : ALIGN (0)BYTE PSECT ($$$105_prologue) INITIAL (BYTE ($$op)); UNDECLARE dpt; %IF $$op EQLU 0 %THEN OWN dpt : ALIGN (0)BYTE PSECT ($$$105_prologue) INITIAL (BYTE (exp)); %ELSE %IF $$op EQLU 1 %THEN OWN dpt : ALIGN (0)WORD PSECT ($$$105_prologue) INITIAL (WORD (exp)); %ELSE %IF $$op EQLU 2 %THEN OWN dpt : ALIGN (0)WORD PSECT ($$$105_prologue) INITIAL (WORD (exp - dpt_tab)) ; %ELSE OWN dpt : ALIGN (0)LONG PSECT ($$$105_prologue) INITIAL (LONG (exp)); %IF ($$op AND ( NOT %X'80')) EQLU 4 %THEN OWN dpt_v : ALIGN (0)BYTE PSECT ($$$105_prologue) INITIAL (BYTE (str_pos, str_siz)); UNDECLARE dpt_v; %FI %FI %FI %FI UNDECLARE dpt, %QUOTE %QUOTE __byte, %QUOTE %QUOTE __word, %QUOTE %QUOTE __long, %QUOTE %QUOTE __convert_op, $$op; %FI %FI %FI %; ! None. !+ ! FIELDS: !- ! None. !+ ! STRUCTURES: !- ! None. !+ ! PSECTS: !- _driver_psects; ! General driver PSECTs. _driver_table_psects; ! PSECTs for device driver tables. !+ ! EQUATED SYMBOLS: !- LITERAL ss_k_def_bufsiz = 65535, ss_k_devtype = 10; !+ ! EXTERNAL REFERENCES: !- FORWARD ROUTINE ss_cancel, ss_devint, ss_error_enable, ss_read_registers, ss_write_registers, ss_unit_init; !+ ! OWN STORAGE: !- FORWARD ss$ddt : BLOCK [ddt$k_length, BYTE] PSECT ($$$115_driver); _dptab (devnam = ss, adapter = uba, ucbsize = ssucb_k_length, name = 'SSDRIVER'); _dpt_store ('INIT'); _dpt_store (ucb, ucb$b_fipl, 'B', 8); _dpt_store (ucb, ucb$b_dipl, 'B', 21); _dpt_store (ucb, ucb$l_devchar, 'L', dev$m_rtm OR dev$m_idv OR dev$m_odv OR dev$m_avl); _dpt_store (ucb, ucb$b_devclass, 'B', dc$_realtime); _dpt_store (ucb, ucb$b_devtype, 'B', ss_k_devtype); _dpt_store (ucb, ucb$w_devbufsiz, 'W', ss_k_def_bufsiz); _dpt_store ('REINIT'); _dpt_store (ddb, ddb$l_ddt, 'D', ss$ddt); _dpt_store (crb, _field_op (crb$l_intd, +, 4, 0, 0, 0), 'D', ss_devint); _dpt_store (crb, _field_op (vec$l_unitinit, +, crb$l_intd), 'D', ss_unit_init); _dpt_store ('END'); _ddtab (devnam = ss, functb = ss_r_functable, cancel = ss_cancel, ! legal = (readvblk, readlblk, readpblk, writevblk, writelblk, writepblk, setmode), ! buffered = (readvblk, readlblk, readpblk, writevblk, writelblk, writepblk), ! actions = ((ss_read_registers, (readlblk, readpblk)), ! (ss_write_registers, (writelblk, writepblk)), ! (ss_error_enable, (setmode)))); ! !+ ! BUILTIN DECLARATIONS: !- ! None. ROUTINE ss_cancel = 1; ROUTINE ss_devint = 1; ROUTINE ss_error_enable = 1; ROUTINE ss_read_registers = 1; ROUTINE ss_write_registers = 1; ROUTINE ss_unit_init = 1; END ! End of module MODNAME ELUDOM