Annotation of driverkit/doc/OLD_NRW/NRWDeviceDriver.frame, revision 1.1

1.1     ! root        1: <MakerFile 2.0J>
        !             2:    
        !             3: 
Aa��@"�&ff&�����HH      $ d&&       &&&&&d&&&&Footnote*��. � �&&&&&&&Zm&:[&
        !             4: &&1Head2Head&x(IOReturn)devEjectDisk(IOReturn)getPhysParams(IOReturn)isDiskPresent
(IOReturn)rtn(IOReturn)setFormatted(IOReturn)someMethod(boolean_t)isDiskOpen(dev_port_t)dev_port(dev_port_t)getDevPort(int)channelNum(int)ioReturnToErrno(int)netInit
(int)netInput(int)registerDevice(int)someArgument(ioResult_t)someMethod(ioReturn_t)devEjectDisk(ioReturn_t)getBlockSize(ioReturn_t)getDevSize(ioReturn_t)rtn(ioReturn_t)setFormatted(netif_t)getNetif(netif_t)realNetif(port_name_t)notifyPort(port_t)IOPort(readyState_t)checkReady(u_int)formattedFlag(u_int)getQueryFlags(u_int)getUnit(unsigned)deviceIntrMask(unsigned)diskIsOpen(unsigned)dma_id(unsigned)getDevIntrMask(unsigned)getIntrSumm  (unsigned)intrSummary&(unsigned)isPhysDevice(void)abortDma(void)abortRequest(void)disableDma(void)diskPresent(void)dmaAbort(void)dmaDisable(void)dmaForceBufAdv(void)dmaReset(void)dmaStart(void)doIoComplete(void)flushIntrMsgs(void)freeDmaFrame(void)incrCollisions(void)incrInErrors(void)incrInPacketsr(void)incrOutErrorsR(void)incrOutPackets(void)registerDisk(void)resetDma(void)setChanIntrCause(void)setChanIntrMaskd(void)setChannelIntrMask(void)setDevIntrCauset(void)setDevIntrMask(void)setDevName(void)setDevPort(void)setDeviceIntrCause(void)setDeviceNamed(void)setDevicePaget(void)setDevicePortB(void)setDeviceSize)(void)setNetif(void)setQueryFlagsr
(void)setUnitd(void)startDma(void)unRegisterDeviceAutoconfiguringtConfigDiskObject:IODeviceaDiskReadyStateIOAttachChannelaIOAttachInterrupttIOChannelCommandIOChannelDequeueOptionIOChannelEnqueueOptionIOChannelReturneIOChannelStatuseIOConfigDeviceIOConfigReturnIOCreateDevicePortIODelayrIODeleteDeviceIODeleteDriverIODequeueDmaIODequeueDma()'dIODescriptorCommandiIODestroyDevicePort)IODetachChannelmIODetachInterruptFIODevToIdMapIODeviceNumberIODeviceNumbersiIODevicePageIODevicePortIODeviceReturnIODeviceTypeIODiskDeviceIODiskDevice:IODeviceoIODmaDirectionIODmaStatusiIOEnqueueDmaIOExitThreadIOForkThreadIOForkThread(IOThreadFcnIOFreeIOGetDeviceTypeC
IOIntToStringCIOIntToString(int)IOLog(constrIOMalloc
        !             5: IOMapBoardIOMapDevicePageD  IOMapSlotIONetDevicea
IOPanic(constvIORegisterDriverIORescanDriverIOResumeThreadIOResumeThread(IOThreadIOReturnIOReturnToStringIOSendChannelCommandIOServerIOSleep(intyIOSlotIdIOSuspendThreadiIOSuspendThread(IOThreadIOTaskIOThread IOTimeoutoIOTimeout(IOThreadFcnc
        !             6: IOUnitName
        !             7: IOUnitTypeIOUnmapBoardIOUnmapDevicePageIOUnmapSlotaIOUntimeoutDIOUntimeout(IOThreadFcnqIOlibIOInitOLaserPrinterLogicalDiskLockeLogicalDisksMyDeviceNetDriver:IODevice
NetDriverKernaOR�dSCSIControllerSCSIDisk  XPRVieweruaThreadeabcdabcdABCDactualLengthaddrargtbcountblockDevblockId[NPART]       blockSizee
        !             8: block_sizebootstrap_infobootstrap_look_upubootstrap_lookup()sbuffer_size    bytesReadubytesWrittencause:(unsigned)causekchan_commandchan_command_tchan_dequeue_opt_tchan_desc_cmd_ttchan_dma_dequeuechan_dma_dequeue()'dchan_dma_enqueuechan_enqueue_opts_tTchan_num
chan_return_tnchan_statuss
chan_status_tOchan_t
channelNumbergchannelRegschannelSpecificO   classNamevcmdecmdBuf
        !             9: cmdBufLockcmdBuf_tcmdLockh
        !            10: configPortconfig_return_tdevPagendevPagePdevPortdevSizendevToIdMap_t
dev_board_map(dev_board_unmapOdev_chan_attachOdev_chan_detachhdev_config_porth    dev_entryedev_get_type       dev_indexcdev_intr_attachOdev_intr_detachB dev_nmbera     dev_num_t
        !            11: dev_numberdev_numbersu
        !            12: dev_page_tdev_portdev_port_<dev_number>adev_port_createadev_port_destroy
        !            13: dev_port_tdev_port_to_typedev_reg_mapi
dev_reg_unmapdev_return_tdev_sizedev_slot_mapdev_slot_unmapdev_tDdev_type
        !            14: dev_type_tdeviceIndex
        !            15: deviceNamedeviceNumber
deviceNumbersc
        !            16: devicePage
        !            17: devicePortdevicePortsk
        !            18: deviceSize
        !            19: deviceType
device_delete
device_masterydevnamen  devname_tsdevrdevsdirndirectDriverdirection_thdiskIddmaAbortdmaFreeFramedma_id
        !            20: dma_statusdma_status_tdoIoComplete        driveNameedriveName[MAXDNMLEN]
        !            21: drive_info
        !            22: driverPort
driverSigPorts
driver_configO
driver_deleteedriver_portndriver_registerS
driver_rescanNdriver_sig_portf  driverkitk     ejectDiskendifheorfexec'dexecutable_fidexecutable_file_name
extDeviceRegszfcnefloppyThreadgetChanRegsgetChanSpecific
        !            23: getDevName
        !            24: getDevPagegetDriveNamegetExternalDev
get_devr_port_human_readable_name
        !            25: idMapArray    if_attachnif_getbuf_func_tif_ipackets_if_output_func_t
        !            26: if_privatein_useindirectDevices_insertNotify    int)countoint)maxCountintDeviceSpecificRegstinternalDevMapinternalDevMap_t     intr_portnioQueue_ioQueueLock_ioReturnText
        !            27: ioReturn_tkernel'slastReadyStatelibDevlibIOelibname
        !            28: livePartIdlockUntil:COMPLETEmask:(unsigned)maskemaxCountnbnetControl(netif_tnetGetBuf(netif_tenetInit(netif_tinetInput(netif_t        netOutput_netOutput(netif_tnnetbuf_tnetifinetif_thnmserverosdevt   ownerPortaparameterArrayphysFlagprobe:deviceMasterprobe:directDriverrawDevrawDevId readAsyncoreadAtreadOpsvreadyState_t     realnetifOregArrayregArray:(regValues_trregTextsregText:regArrayregVal
regValueArrayr       regValuesjregValues_ti
        !            29: reg_valuesregisterLogicalDisk
        !            30: removableP
returnedCountvrvNamervValuelrw
        !            31: setDevPagesizepslotIdslot_id  slot_id_tesprintfastartOpistream_modettarget_task_task_createu       task_portetimeReadingAtimeWritingctsvalgunlockWith:COMPLETEk
        !            32: unregisterusruvolCheckwaitForWorke
        !            33: writeAsyncwriteOpsxprAdd
        !            34: xpr_string&���nt&�&�&-&}&>&-&�Map&.ntr&/&�n&0ue_&1&�ueu&2&�_&3urn&4&�
        !            35: io&5&�n_t&6nel&7&�ast&8Sta&9&�ibD&:ibI&;ibn&<&�
        !            36: li&=tId&@&�kUn&A&�OMP&Bma&C&�nsi&Dmas&UaxC&hnb&iCon&jnet&kne&luf(&�%&�&�&@Ini7second-level heading; headings:second-level[headings:2]_tn&�&1buf7second-level heading; headings:second-level[headings:2]ete&Uy7second-level heading; headings:second-level[headings:2]ra&hd  7second-level heading; headings:second-level[headings:2]egA&ire7second-level heading; headings:second-level[headings:2]
re&jeAr7second-level heading; headings:second-level[headings:2]alD&k
        !            37: re7second-level heading; headings:second-level[headings:2]e&l7second-level heading; headings:second-level[headings:2]m&�&�&�
        !            38: rg&�&-
�k_&�&/
�_c&�&2
�      &�&4
�or&�&5
�me&�&7
�gA&�&9
�Wr&�&<
�&�&A
�&�&C
�Wi
�
�
�
�<$lastpagenum>ck
�<$monthname> <$daynum>, <$year>p
�"<$monthnum>/<$daynum>/<$shortyear>
�;<$monthname> <$daynum>, <$year> <$hour>:<$minute00> <$ampm>_
�"<$monthnum>/<$daynum>/<$shortyear>
�<$monthname> <$daynum>, <$year>
�"<$monthnum>/<$daynum>/<$shortyear>ma
�     <$fullfilename>C
�
        !            39: <$filename>
�<$paranum[ChapterNum]>&@
�<$paratext[ChapterTitle]>ngs
�&
<$curpagenum>s:2
�
<$paratext[1Head]> h
�
        !            40: <$marker1>ec
�
�Page #page <$pagenum>ond
�Heading & Page<$paratext> on page <$pagenum>
�StatusPRELIMINARYadi
�
Figure Number-
        !            41: <$paranum>
�Heading<$paratext>v
�Pagepage <$pagenum>-
�Section & Page%section <$paranum> on page <$pagenum>su�u  v..krey::h&Aiz22c&A-{;;2|5�d&Av}77d&As~88einPPg&A-�RR2QO        >or
3�me
�&9
�
�&C

+�
tpa
�
thnSYNOPSIS
$ye
-"&hn
-$da
hor
�
thn 
*ynu!
r> "�$mi#�$am$
"%
m>/&�/<$'�>(�$mo)
<$dSUMMARY*
�+
thnSYNOPSIS,
hor-
�  .
lfi/
 �
        !            42: 0�ena1
2
[Ch3
>&@4
$paSUMMARY5
Ble]6�
7
numSYNOPSIS8
ate9
> h:
$ma;
 �<
Pa=
e <>
3ond?
din@
<$SUMMARYA
  <$B
�SUMMARYC
NARSYNOPSISD
NumE
araF
HeG
 $paH
�I
ageJ
m>-SUMMARYK
ageSYNOPSISL
um>M
<$pN
 O
u        P
v.Q
R
:hSUMMARYS
2cSYNOPSIST
;2U
V
 &AvW
}7X�Note:  eY
Z
PgSUMMARY[
R2SYNOPSIS\
�me]
�&9^��_
 �&C`
a
�b
tpac��d�thne
SISf
�ģg
-&h�$dai
3horj
�SUMMARYk� 
*l
3!
m
3"�n�#�o
$
p
%
&2.&�q
r
&&1.s
<$d&3.RYt��u�thnv
SISw
x
SYNOPSISy
�
        !            43: z
ena{
 |
[Ch}
>&@~�$paNote:  �le]�

�
numSUMMARY�
ateSYNOPSIS�
:
�
;
 �
 <
�
=
SUMMARY�
SYNOPSIS�
<$�
RY�
�
�
 C
�
YNO�
Num�
araSUMMARY�
G
 SYNOPSIS�
�
�
 �
K
�
YNO�
um>SUMMARY�
N
 SYNOPSIS�
�
�
 �
�
S
SUMMARY�
T
SUMMARY�
SYNOPSIS�
}7�
�
  e�
SUMMARY�
RY�
SUMMARY�
SYNOPSIS�
��
�&C�
 �
��
tpa�
�SUMMARY�
e
SYNOPSIS�
��
�
 �
�
�
k�SUMMARY�
SYNOPSIS�
#��
$
�
 %
�
&��
�
&&�
s
�
3.�
��
thn�
SIS�
�
SUMMARY�
�
        !            44: �
enaSYNOPSIS�
|
�
}
�
~��
 ote�
le]�

�
numSUMMARY�
ate�
SISSYNOPSIS�
;
 �
<
�
 =
�
RY�
SUMMARY�
�
SYNOPSIS�
�
C
�
 YNO�
Num�
araSUMMARY�
G
 �
SISSYNOPSIS�
�
�
 K
�
YNO�
um>SUMMARY�
N
 �
SISSYNOPSIS�
�
�
 �
S
�
RYSUMMARY�
RY�
SYNOPSIS�
�
�
 ��Note:  ��Note:  ��RY�
�
�
�
B�
���
 �
B�
�
B�
�
B�
�
BUMM�
e
�
SIS�
B�
B�
B�
B�
B�
B�
B�
�
BYNO
B#�&
B$

B%

&�

B&&
Bs

B3.
B�      
Bthn
        !            45: 
BSIS�
      �MM

 �
�
 ena�NO
 �
�
}

~�
ote
le]
 
�

 �Y
 ate�


�
��
��
 ��

�

UMM

 
SIS!
"
#
$
%
B&
B�
'
B�
(
BYNO)
B*
B+
BK
,
BYNO-
Bum>.
BRY/
B0
B1
�
2
�
3
�
 4��
5
B�
6
UMM7
BRY8
B9
BSIS:
B;
B<
B=
>
��?�ote@
RYA
B
�
C
�
D��
 E
�
F��
G
B�
H
BUMMI
Be
J
BSISK
L
M
N
O
BP
BQ
B�
R
YNOS
#�T
$
U
B%
V
B&�W�X
&&Y
s
Z
3.[
 ��
B\
 �IS]
 ��^
 �MM_
 �
�`
Benaa
B
 b
Bc
Bd
Be
Bf
Bg
Bh
Bi
B
 j
B
k
Bl
Bm
Bn
Bo
Bp
Bq
Br
Bs
Bt
Bu
Bv
Bw
Bx
By
Bz
B{
B|
}
B~
B
B�
B�
B�
B�
B�
B�
B�
B�
B�
�
�
�
�
�
�
B�
B�
B�
B�
B�
B�
B�
B�
�
�
�
�
B�
B���
�
B�
�
B�
B�
B�
B�
�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B]
 �
B�
B�
B�
��`
B�
Ba
B�
Bb
B�
Bc
B�
Bd
B�
Be
B�
Bf
B�
Bg
B�
h
B�
Bi
B�
Bj
B�
Bk
B�
l
B�
m
B�
n
B�
Bo
B�
Bp
B�
Bq
B�
Br
B�
Bs
B�
Bt
B�
Bu
B�
Bv
B�
Bw
B�
Bx
B�
By
B�
Bz
B�
B{
B�
B|
�
B}
B�
B~
B�
B
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
�
B�
�
B�
�
B�
�
B�
�
B�
�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
�
B�
�
B�
�
B�
�
�
B�
�
B�
B���
B�
�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
�
�
B�
�
B�
�
B�
B�
B�
�
B�
�
B�
B�
B
�
B&
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B       
B�
B
        !            46: 
B��
�
B
�
B

�
B
      �
B�
 e
B�
B
 �
B
 �
�
i
B�j
B
Bk
B
Bl
B
Bm
B
Bn
B
Bo
B
Bp
B
q
B
Br
B
Bs
B
Bt
B
Bu
B
Bv
B 
Bw
B!
Bx
B"
By
B#
Bz
B$
B{
B%
B|
&
B}
B'
~
B(

B)
�
B*
B�
B+
B�
B,
B�
B-
B�
B.
B�
B/
B�
B0
B�
B1
B�
2
B�
3
B�
4
B�
5
B�
6
B�
7
B�
B8
B�
B9
B�
B:
B�
B;
B�
B<
B�
B=
B�
B>
B�
B?
B�
@
B�
A
B�
B
B�
C
B�
BD
B�
BE
��F��
G
B�
BH
B�
BI
B�
BJ
B�
BK
B�
BL
B�
M
B�
BN
B�
BO
B�
BP
B�
BQ
B�
BR
B�
BS
B�
BT
B�
BU
B�
BV
B�
BW
B�
BX
�
BY��
BNote:  BZ

B[�
B\
       
B]

        !            47: 
B^

_

`


a

      b
c
d
e

 f
g
h
i
j
k
l
m
n�o
Bp
q
SUMMARYr
u
BSYNOPSISs
 
Bt
!
Bu
"
Bv
#
Bw
$
Bx
 %
By
&
Bz
'
{
(
|
)
}
*
B~
+
B
,
BSUMMARY�
SYNOPSIS�
�
B�
�
B�
�
�
�
�
 �
�
�
�
�
�
�
SUMMARY�
8
BSYNOPSIS�
�
�
�
�
�
�
 �
�
�
�
�
�
�
�
�
SUMMARY�
�
BSYNOPSIS�
K
B�
L
B�
M
B�
N
B�
 O
B�
P
B�
Q
B�
R
BSUMMARY�
SYNOPSIS�
�
B�
�
B�
�
B�
�
B�
�
B�
  B�
 �
�
�
�
�
�
�
SUMMARY�
SYNOPSIS�
e
�
f
�
g
�
h
�
i
�
 j
�
k
�
l
�
m
SUMMARY�
SYNOPSIS�
�
�
RY�
�
s
�
t
�
u
�
v
�
w
�
x
 �
y
�
z
�
{
�
|
�
}
�
~
�

�
UMMSUMMARY�
YNOSYNOPSIS�
�
�
�
�
�
�
�
 �
�
�
�
�
 �
�
UMM�
8
B�
SISSUMMARY�
SYNOPSIS�
�
�
�
�
�
�
�
 �
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
UMM�
�
B�
SIS�
�
�
SUMMARY�
O
BSYNOPSIS�
�
�
�
�
UMM�
�
SIS�
�
 �
���
�
SUMMARY�
SYNOPSIS�
�
�
�
�
�
�
�
�
�
�
 UMM�

SIS&


!
!
!
!
!
       

        !            48: 
�
SUMMARY
�
SYNOPSIS


















�

YNO
�
 
�
!
�
"
�
 #
�
$
�
%
�
&
UMM'
!8
B(
!SIS)
!RY*
!+
!�
,
�
-
�
.
�
/
�
SUMMARY0
SYNOPSIS1
�
2
�
3
�
4
�
5
�
6
UMM7
�
B8
SIS9
:
;
 <
RY=
>
�
?
�
@
�
A
!�
B
!�
C
!�
D
!�
 E
�
F
��G
�
H
�
I
UMMJ
K�SISL�M
BN
BO
BP
BQ
BR
BS
BT
BU
BV
BW
BX
BY
BZ
B[
B\
B]
B^
B
_
BYNO`
Ba
Bb
c
d
Be
Bf
Bg
Bh
Bi
Bj
Bk
Bl
Bm
n
      �
o
Bp
Bq
r
s
t
u
v
Bw
Bx
By
Bz
B{
B|
B}
B~
B
B�
B�
B�
B�
B�
B0
�
BYNO�
B�
�
B�
�
B�
�
B�
�
B�
�
BUMM�
B�
B�
BSIS�
B�
B�
B�
BRY�
B�
B�
�
B�
�
B�
�
B�
�
B�
�
B�
�
B�
 �
B�
�
B���
B�
�
B�
�
BUMM�
B�
BSIS�
�
�
�
�
�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B
�
BYNO�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
Bo
B�
Bp
B�
Bq
�
Br
�
Bs
�
Bt
�
Bu
�
Bv
B�
Bw
B�
Bx
B�
By
B�
Bz
B�
B{
B�
|
B�
}
B�
~
B�

B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B��
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
�
B�
�
B�
�
B�
�
B�
�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B
�
B&
B�
B
B�
B
B�
B
B�
B
B�
B��
B
B�
B
B�
B   
B�
B
        !            49: 
B�
B
B�
B
B�
B

B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B 
B�
B!
B�
B"
B�
B#
B�
B$
B�
B%
B�
B&
B�
'
B�
(
B�
)
B�
*
B�
B+
B�
B,
B�
B-
B�
B.
B�
B/
B�
B0
B�
B1
B�
B2
B�
B3
B�
B4
B�
B5
B�
B6
B�
B7
B�
B8
B�
B9
�
B:
�
B;
�
B<
�
B=
B�
B>
B�
B?
B�
B@
B�
BA
B�
BB
B�
BC
B�
BD
B�
BE
B�
BF
B�
BG
B�
BH
�
BI
B�
BJ
�
BK
B�
BL
B�
BM
�
BN
B�
BO
B�
BP
�
BQ
�
BR
�
BS
�
BSUMMARYT
SYNOPSISU
�
BV��
BW
�
BX
�
BY��
BZ
�
B[
�
B\
�
B]
�
B^
�
B_
 �
B`��
Ba
�
Bb
�
Bc
�
Bd
�
Be
�
BSUMMARYf

Bg

BSUMMARYh
SYNOPSISi
B�
Bj
�
Bk
�
Bl
�
Bm
�
Bn
�
Bo
�
Bp
 �
Bq
�
BSYNOPSISr
!
Bs
"
Bt
#
BSUMMARYu
v
      �
w
'
BSYNOPSISx
     �
y
*
BSYNOPSISz
     �
B{
-
B|
.
B}
/
B~
0
BSUMMARY�Note:  �
�
BSYNOPSIS�
5
B�
6
B�
7
B�
 8
B�
 9
�
 :
�
;
�
     <
��
�
B�
�
B�
�
B�
�
B���
B�
�
B�
�
B�
�
B�
�
B�
�
B�
 �
B�
�
 �
B�
 J
��
 �
B�
B�
 �
B�
N
B�
     O
B��
 �
B�
�
 �
B�
 S
���RY�
�
BU
�
V��
W
�
BX
�
BY��
BZ
�
B[
�
B\
�
B]
�
B^
�
B_
 �
B`��
Ba
�
Bb
�
c
�
d
�
e
�
UMM�

B�

B�
BRY�
�
Bi
B�
Bj
��k
�
Bl
�
m
�
Bn
�
 o
��
 �
B�
�
 �IS�
 !
B�
�
�
�
u
�
v
 �
B
�
�
Bx
     �
B
�
B�
Bz
     �

B�
B�
�
B�
B����
Bote�
�
B�
BSIS�
�
B�
�
�
B�
�
B�
 �
B�
B�
B�
�
B�
�
B�
B�
B�
�
B�
B�
B�
B�
B�
B�
B�
 �
B�
�
B�
�
B�
B�
     �

B���
�
B�
�
 �

B�
�
B�
�
B�
B�
     �
!
B�
B�
BRY�
�
U
�
V��
BW
�
X
�
BY��
Z
�
B[
�
B\
�
B]
�
B^
�
B_
 �
B`��
Ba

Bb
&
Bc

Bd

Be

BUMM
B
B
B
B
BRY
B   
Bi
B
        !            50: 
Bj

Bk

Bl


Bm

Bn

Bo

B�
  
B

B
B!
B
B�

B�

B�

B�

B�
B
B�

B�
B
B�
B
B�
B
�
B��

�
B 
�
!
B�
B"
�
BSYNOPSIS#
$
%
&
'
 �(
)
B*
B+
B,
B-
B.
B/
B0
B1
B2
B3
B4
B5
B6
B7
B8
B9
B:
B;
B<
B=
B>
B?
B@
BA
BB
BC
BD
BE
BF
BG
BH
BI
BJ
BK
BL
BM
BN
BO
BP
BQ
BR
BS
BT
BU
BV
BW
BX
BY
BZ
B[
B\
B]
B^
B_
B`
Ba
Bb
Bc
Bd
Be
Bf
Bg
Bh
Bi
Bj
Bk
Bl
Bm
Bn
Bo
Bp
Bq
Br
Bs
Bt
Bu
Bv
Bw
Bx
B#
y
B$
z
B%
{
B&
|
B'
 }
B(
~
B)
B
B*
B�
B+
B�
B,
B�
B-
B�
B.
B�
B/
B�
B0
B�
B1
B�
B2
B�
B3
B�
B4
B�
B5
B�
B6
B�
B7
B�
B8
B�
B9
B�
B:
B�
B;
B�
B<
B�
B=
B�
B>
B�
B?
B�
B@
B�
BA
B�
BB
B�
BC
B�
BD
B�
BE
B�
BF
B�
BG
B�
BH
B�
BI
B�
BJ
B�
BK
B�
BL
B�
BM
B�
BN
B�
BO
B�
BP
B�
BQ
B�
BR
B�
BS
B�
BT
B�
BU
B�
BV
B�
BW
B�
BX
B�
BY
B�
BZ
B�
B[
B�
B\
B�
B]
B�
B^
B�
B_
B�
B`
B�
Ba
B�
Bb
B�
Bc
B�
Bd
B�
Be
B�
Bf
B�
Bg
B�
Bh
B�
Bi
B�
Bj
B�
k
B�
l
B�
m
B�
Bn
B�
Bo
B�
Bp
B�
Bq
B�
Br
B�
Bs
B�
Bt
B�
Bu
B�
Bv
B�
Bw
B�
Bx
B�
By
B�
Bz
B�
B{
B�
B|
B�
B}
B�
B~
B�
B
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
�
B�
�
B�
�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B
B�
B&
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B   
B�
B
        !            51: 
B�
B
B�
B
B�
B

B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�

B�

B�

B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B 
B�
B!
B�
B"
B�
B#
B�
B$
B�
B%
�
B&
�
B'
�(
�
B)
B�
B*
B�
B+
B�
B,
B�
B-
B�
B.
B�
B/
B�
B0
B�
B1
B�
B2
B�
B3
B�
B4
B�
B5
B�
B6
B�
B7
B�
B8
B�
B9
B�
B:
B�
B;
B�
B<
B�
B=
B�
B>
B�
B?
B�
B@
B�
BA
B�
BB
B�
BC
B�
BD
B�
BE
B�
BF
B�
BG
B�
BH
B�
I
B�
J
B�
K
B�
BL
B�
BM
B�
BN
B�
BO
B�
BP
B�
BQ
B�
BR
B�
BS
B�
BT
B�
BU
B
BV
B&
BW
B
BX
B
BY
B
BZ
B
B[
B
B\
B
B]
B
B^
B    
B_
B
        !            52: 
B`
B
Ba
B
Bb
B

Bc
B
Bd
B
Be
B
Bf
B
Bg
B
Bh
B
Bi
B
Bj
B
Bk
B
Bl
B
Bm
B
Bn
B
Bo
B
Bp
B
Bq
B
Br
B
Bs
B
Bt
B
Bu
B 
Bv
B!
Bw
B"
Bx
B#
By
B$
Bz
B%
{
B&
|
B'
}
B(
~
B)
B
B*
B�
B+
B�
B,
B�
B-
B�
B.
B�
B/
B�
B0
B�
B1
B�
B2
B�
B3
B�
B4
B�
B5
B�
B6
B�
B7
B�
B8
B�
B9
B�
B:
B�
B;
B�
B<
B�
B=
B�
B>
B�
B?
B�
B@
B�
BA
B�
BB
B�
BC
B�
BD
B�
BE
B�
BF
B�
BG
B�
BH
B�
I
B�
J
B�
BK
B�
L
B�
BM
B�
BN
B�
BO
B�
BP
B�
BQ
B�
BR
B�
BS
B�
BT
B�
BU
B�
BV
B�
BW
B�
BX
B�
BY
B�
BZ
B�
B[
B�
B\
B�
B]
B�
B^
B�
B_
B�
B`
B�
Ba
B�
Bb
B�
Bc
B�
Bd
B�
Be
B�
Bf
B�
Bg
B�
Bh
B�
Bi
B�
Bj
B�
Bk
B�
Bl
B�
Bm
B�
Bn
B�
Bo
B�
Bp
B�
Bq
B�
Br
B�
Bs
B�
Bt
B�
Bu
B�
Bv
B�
Bw
B�
Bx
B�
By
B�
Bz
B�
B{
B�
B|
B�
B}
B�
B~
B�
B
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
�
B�
  �
��
 J
B�
B�
 �
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B
B�
B&
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B       
B�
B
        !            53: 
B�
B
B�
B
B�
B

B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B 
B�
B!
B�
B"
B�
B#
B�
B$
B�
B%
B�
B&
B�'
B�
B(
B�
B)
B�
B*
B�
B+
B�
B,
B�
B-
B�
B.
B�
B/
B�
B0
B�
B1
B�
B2
B�
B3
B�
B4
B�
B5
B�
B6
B�
B7
B�
B8
B�
B9
B�
B:
B�
B;
B�
B<
B�
B=
B�
B>
B�
B?
B�
B@
B�
BA
B�
BB
B�
BC
B�
BD
B�
BE
B�
BF
B�
G
B�
      H
BI
BJ
BK
B�
BL
B�
BM
B�
BN
B�
BO
B�
BP
B�
BQ
B�
BR
B�
BS
B�
BT
B�
BU
B
BV
B&
BW
B
BX
B
BY
B
BZ
B
B[
B
B\
B
B]
B
B^
B       
B_
B
        !            54: 
B`
B
Ba
B
Bb
B

Bc
B
Bd
B
Be
B
Bf
B
Bg
B
Bh
B
Bi
B
Bj
B
Bk
B
Bl
B
Bm
B
Bn
B
Bo
B
Bp
B
Bq
B
Br
B
Bs
B
Bt
B
Bu
B 
Bv
B!
Bw
B"
Bx
B#
By
B$
Bz
B%
B{
B&
B|
B'
B}
B(
B~
B)
B
B*
B�
B+
B�
B,
B�
B-
B�
B.
B�
B/
B�
B0
B�
B1
B�
B2
B�
B3
B�
B4
B�
B5
B�
B6
B�
B7
B�
B8
B�
B9
B�
B:
B�
B;
B�
B<
B�
B=
B�
>
B�
?
B�
@
B�
BA
B�
BB
B�
BC
B�
BD
B�
BE
B�
BF
B�
BG
B�
BH
B�
BI
B�
BJ
B�
BK
B�
BL
B�
BM
B�
BN
B�
BO
B�
BP
B�
BQ
B�
BR
B�
BS
B�
BT
B�
BU
B�
BV
B�
BW
B�
BX
B�
BY
B�
BZ
B�
B[
B�
B\
B�
B]
B�
B^
B�
B_
B�
B`
B�
Ba
B�
Bb
B�
Bc
B�
Bd
B�
Be
B�
Bf
B�
Bg
B�
Bh
B�
Bi
B�
Bj
B�
Bk
B�
Bl
B�
Bm
B�
Bn
B�
Bo
B�
Bp
B�
Bq
B�
Br
B�
Bs
B�
Bt
B�
Bu
B�
Bv
B�
Bw
B�
Bx
B�
By
B�
Bz
B�
B{
B�
B|
B�
B}
B�
B~
B�
B
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
�
B�
�
B�
�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B
B�
B&
B�
B
B�
B
B�
B
B�
B
  �
B�
 \
B�
B
 �
B
 �
B�   
B`
B
        !            55: 
Ba
B
Bb
B
Bc
B

Bd
B
Be
B
Bf
B
g
B
h
B
Bi
B
Bj
B
Bk
B
Bl
B
Bm
B
Bn
B
Bo
B
p
B�q
B
r
B
s
B
  t
B�
B
 �
B
 �
B� 
x
B!
By
B"
Bz
B#
{
B$
B|
B%
B}
B&
B~
B'
B
B(
B�
B)
B�
B*
B�
B+
*�
B,��
B-
)�
B.
B�
B/
B�
B0
B�
B1
�
B2��
B3
B�
B4
B�
B5
B�
B6
B�
B7
�
B8
�
B9
�
B:
�
BSUMMARY;��
BLIBRARY<
SYNOPSIS=
�
B>
�
B?
 �
B@
B�
BA
�
BB
B�
BC
B�
BD
B�
BE
B�
BF
B�
BG
B�
BH
B�
BI
B�
BJ
B�
BK
B�
BL
B�
BM
B�
BN
B�
BO
B�
BP
B�
BQ
B�
BR
B�
BS
B�
BT
B�
BU
B�
BV
B�
BW
B
 X
B
BY
BZ
B�
B[
B   
B\
B
        !            56: 
B]
B
B^
B
B_
B

B`
B
Ba
B
Bb
B
c
B
d
B
Be
B
Bf
B
Bg
B
Bh
B
Bi
B
Bj
B
Bk
B
l
B�m
B
n
B
o
B
  p
B
Bq
Br
B�
Bs
B 
t
B!
Bu
B"
Bv
B#
w
B�x
B%
By
B&
Bz
B'
B{
B(
B|
B)
B}
B*
B~
B+
*
B,��
B-
)�
B.
B�
B/
B�
B0
B�
B1
�
B2��
!3
B�
!4
B�
5
B�
B6
B�
B7
�
B8
�
9
�
     :
��
RY�
     �Y�
 �NO�
 =
��
 �
B�
 �
B�
     �
B�
BB
B�
BC
B�
BD
B�
BE
B�
BF
B�
BG
B�
BH
B�
BI
B�
BJ
B�
BK
B�
BL
B�
BM
B�
BN
B�
BO
B�
BP
B�
BQ
B�
BR
B�
BS
B�
BT
B�
BU
B�
BV
B�
BW
B�
BX
B�
BY
B�
BZ
B�
B[
B�
B\
B�
B]
B�
B^
B�
B_
B�
B`
B�
Ba
B�
Bb
B�
Bc
B�
Bd
B�
Be
B�
Bf
B�
Bg
B�
Bh
B�
Bi
B�
Bj
B�
Bk
B�
Bl
B�
Bm
B�
Bn
B�
Bo
B�
Bp
B�
Bq
B�
Br
B�
Bs
B�
Bt
B�
Bu
B�
Bv
B�
w
B�
Bx
B�
By
B�
z
B�
B{
B�
|
B�
B}
B�
B~
B�
B
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
!�
B�
!�
B�
�
B�
B�
B�
B�
B�
B�
B�
�
B�
 �
B�
B�
B�
B�
B�
     �
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B�
B
B�
B&
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B       
B�
B
        !            57: 
B�
B
B�
B
B�
B

B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
B�
B
)�
B
)�
B
)�
B
)�
B
)�
B
)�
 
)�
B!
)�
B"
B�
#
B�
B$
B�
%
B�
B&
B�
B'
B�
B(
�
B)
�
B*
�
B+
  �
B�,
�
BSUMMARY-
�
B.
�
BSYNOPSIS/
0
1
2
3
4
5
 6
7
8
9
SUMMARY:
;
SYNOPSIS<
�
B=
�
B>
�
B?
�
BSUMMARY@
A
B
 C
D
E
SYNOPSISF
�
BG
�
BH
�
BI
�
BJ
B�
BK
B�
BL
 �
BM
�
BN
B�
B���d�
B.2�
Bd�
B�
B$6��
B$6�)!|
B#
        !            58: ��
        !            59: ��UUh'
Z
B'&UlibDev - Standard IODevice Classes
        !            60: 
BB����UT`(
[       IODevice
        !            61: ]UMUR�� C
U
B]This is the superclass of all device driver classes. It contains minimal state information - BjUHUR��C
U
BTdevice name, unit number, and device page pointer, device port. (Note - the current 
BwUCUR��C
UXIODevice.h actually contains a number of other variables which will probably be deleted 
�U>UR��C
UWbefore final release; most of these deal with a prototype Remote Object implementation �U9UR��@C
UISTwhich is being discarded soon.) The primary areas of functionality of IODevice are:
        !            62: �U4UR��`
U
;Manipulation of standard NRW device and channel registers.
        !            63: �U/UR��`
U
B Common DMA operations. 
        !            64: �U*UR�� 
U
BXStandard device probe and driver startup (the interface of which is defined in IODevice ��U%UR��@
U9but which is implemented by device-specific subclasses).
        !            65: &U UR�� 
USOnce the Remote Object (RO) mechanism is finalized, there will probably be some RO ses&UUR��@
U(support in IODevice as well.
        !            66: C&G������`D
\suIODevice Interface
        !            67: e d&`������`Q
Ico#import <objc/Object.h>
        !            68: ma&l������`&
I��##import <driverkit/deviceCommon.h>
        !            69: nd &x������`M
Ir,!#import <architecture/m88k/io.h>
        !            70: B&�������`
I&
        !            71: O&�������`
Ico@interface IODevice: Object
        !            72: bl&�������`
Iab{
        !            73: &�������`"
IUR  @private
        !            74: &�������`#
Iea&
        !            75:  &�������`G
I wint_unit;
        !            76: o&�������`H
ItaIOUnitName_deviceName;
        !            77: &�������`6
IrdIOUnitType_deviceType;
        !            78: &�������`I
IDe*volatile IODevicePage*_devicePage;
        !            79: &�������`J
I d IODevicePort_devicePort;
        !            80: U/&�������`
I C
        !            81: ������`
I
        !            82: /*
        !            83: UR������`
Ida7  * ...Other private or soon-to-be-obsolete instance 
        !            84: h i ������`     
Iic/ *    variables deleted from this document...
        !            85: d b,������`
        !            86: 
Isu */
        !            87: s8������`
I}
        !            88: ST�UR��`K
QObP_unit
U is a device-relative unit number, analogous to a Unix �minor� number.
        !            89: mT�UR��`L
QODD_deviceName
U is an ASCII string like �sd0� or �en0� or �sound2�.
        !            90: ��d �!!�#i$6�!� d $6�#| e/0o.{T�UR��`7
U&
        !            91: URUR�� 8
QV_deviceType
U is an ASCII string like �SCSIDisk� (Maybe more general, like �Disk� - UMUR��@8
U#TBD...)
        !            92: ��.UHUR��`M
Qi;_devicePage
U is a pointer to a driver�s register space.
        !            93: eNaHUCUR�� N
Q6__devicePort
U is a port by which a driver authenticates its ownership of a particular device e;
        !            94: UU>UR��N
U dQwhen communicating with the kernel (See the section entitled Kernel Level Driver /bU9UR��@N
U
        !            95: Support).
        !            96: z������`O
I s/*
        !            97: o-b�������`P
Ie G * A Kernel level driver should implement one of these probe methods. 
        !            98: d b�������`Q
Isu *
        !            99: /
        !           100: s�������`R
I4 * All probe methods return id of the instantiated 
        !           101: ve�������`S
Iog9 * driver on successful initialization; else return nil.
        !           102: c�������`T
ICI *
        !           103: ing�������`U
I0�1 * Direct device driver (connected to hardware).
        !           104: �������`V
I */
        !           105: �������`W
IE+ probe:(IODeviceNumber)devNumber deviceMaster:(port_t)deviceMaster;
        !           106: R�������`X
IUR&
        !           107: R�������`Y
Iic/*
        !           108: 
U�������`Z
Ing; * Indirect device driver (connected to another IODevice).
        !           109: ��&
        !           110: ������`[
I�� */
        !           111: UR&������`\
Iic+ probe:directDriver;
        !           112: &"������`]
Ite&
        !           113: p&.������`^
I��/*
        !           114: Q6&:������`_
Iis) * Pseudo device (connected to nothing).
        !           115:  &F������``
Iti */
        !           116: de&R������`a
I��        + probe;
        !           117: h&^������`b
Uit&
        !           118: h&j������`
Ise/*
        !           119:  en&v������`R
Il ; * Initialize common instance variables. Typically invoked
        !           120: /*&�������`S
IP1 * via [super init:] in subclass's init: method.
        !           121:  &�������`T
Iho */
        !           122:  b&�������`O
Isu- init;
        !           123: ��&�������`U
I *&
        !           124: l&�������`�
Iur/*
        !           125: of &�������`�
Ive@ * Free up resources used by this device; invoke Object's free.
        !           126:  r&�������`�
I��; * Instance will be �gone� upon return. Typically invoked 
        !           127: ive&�������`�
I? * by subclass; each subclass should implement this method to 
        !           128: :(I&�������`�
Ium2 * free up resources particular to that subclass.
        !           129: &�������`�
I�� */
        !           130: Y&�������`V
I��&
        !           131: ��}����`P
Iec- free;
        !           132: ri�z����`�
Ian&
        !           133: e�w����`�
I��/*
        !           134: ��*�t����`�
I��E * Register/unregister instance with nmserver (or IOServer or ...). 
        !           135: �6�q����`�
I6) * devname must be valid for both calls.
        !           136: nB�n����`�
I
        !           137:   */
        !           138: ��N�k����`�
Ide- (int)registerDevice;
        !           139: robZ�h����`�
Ib- (void)unregisterDevice;
        !           140: d"�ni##�e $6�#�"��$6�!+| su6's������`�
I��&
        !           141: �������`�
I b/*
        !           142: ��������`�
Iit  * Get/Set instance variables. 
        !           143: ��)������`�
If  */
        !           144: ��5������`�
Ire4- (void)setDeviceName: (const char *)name;
        !           145: eeA������`�
I�- (const char *)deviceName;
        !           146: �M������`�
Ica&- (void)setUnit: (u_int)Unit;
        !           147: Y������`�
I s- (u_int)unit;
        !           148: plee������`�
Io 9- (void)setDevicePort: (IODevicePort)devicePort;
        !           149: oq������`�
I��- (IODevicePort)devicePort;
        !           150: ��}������`�
I�}&
        !           151: ��������`�
Iee/*
        !           152: �z�������`�
I
        !           153: e6 * Convert an IOReturn to text. Subclasses which add 
        !           154: �������`�
Ins: * additional IOReturn's should override this method and 
        !           155: �������`�
IusE * call [super IOReturnToString:] if the desired value is not found.
        !           156: ��������`�
Ite */
        !           157: e;�������`�
I�.- (const char *)ioReturnText: (IOReturn)rtn;
        !           158: �������`�
Ini&
        !           159: �������`�
Ie /*
        !           160: 6�������`�
I( * Convert an IOReturn to a Unix errno.
        !           161: �������`�
I�� */
        !           162: ��&&������`�
I��/- (int)ioReturnToErrno        : (IOReturn)rtn;
        !           163: Set&
������`
Is.&
        !           164: �&������`�
If /*
        !           165: 
        !           166: ��&%������`�
Ire: * General purpose get/set parameter methods. IODevice�s 
        !           167: &1������`�
I- " * versions return IO_DR_INVALID.
        !           168: &=������`�
Ioi */
        !           169: ni&I������`j
IC- (IODeviceReturn)getParameterInt : (IOParameterName)parameterName
        !           170: voi&U������`k
I)   maxCount : (unsigned int)maxCount
        !           171: �&a������`l
Iic   parameterArray : 
        !           172: �&m������`m
I��(   (unsigned int *)parameterArray
        !           173: 
        !           174: e&y������`n
IRe   returnedCount : 
        !           175: hi&�������`o
I��(   (unsigned int *)returnedCount;
        !           176: ov&�������`p
I a&
        !           177: 
        !           178: &�������`q
IusD- (IODeviceReturn)getParameterChar : (IOParameterName)parameterName
        !           179: 
        !           180: �&�������`r
Ite)   maxCount : (unsigned int)maxCount
        !           181:  &�������`s
IIO   parameterArray : 
        !           182: �&�������`t
I��)   (unsigned char *)parameterArray
        !           183: n&�������`u
Io    returnedCount : 
        !           184: ��&�������`v
I��(   (unsigned int *)returnedCount;
        !           185:   &�������`w
In;
        !           186: ��&�������`x
I
        !           187: �C- (IODeviceReturn)setParameterInt : (IOParameterName)parameterName
        !           188: get&�������`y
Iho$    count : (unsigned int)count
        !           189:  *    �}����`z
IO_    parameterArray : 
        !           190: �z����`{
I��)   (unsigned int *)parameterArray;
        !           191: r!�w����`|
INa&
        !           192: p-�t����`}
I��D- (IODeviceReturn)setParameterChar : (IOParameterName)parameterName
        !           193: ��9�q����`~
Iar%     count : (unsigned int)count
        !           194: E�n����`
Int     parameterArray : 
        !           195: ��Q�k����`�
Iet,     (unsigned char *)parameterArray;
        !           196: (]�h����`�
Iur 
        !           197: unti�e����`i
Ip&
        !           198: au�b����`
Iq@end
        !           199:  ��_����`�
ItP&
        !           200: md$�te%%�r$6�%�$in$6�5'|ar     Ar
UT
UT��`1
`��&
        !           201: t0UR
UT��`
`si&
        !           202: dSUP
UT��`
`rr&
        !           203: nvUN
UT��`
`o &
        !           204: �UL
UT��`
` :&
        !           205: ��UJ
UT��`
`��&
        !           206: �UH
UT��`
`nt&
        !           207: r&UF
UT��` 
`��&
        !           208: �&%UD
UT��`!
`��&(table of contents goes on this page)
        !           209: d&�)p''���$6�'�&ig$6�%)|  $me
        !           210: ��
        !           211: ��UUh"
[��&@
ZIntroduction
        !           212: (B����UT`c
[amScope
        !           213: ]UMUR�� 
U|WThis document provides a description of the software development environment available etejUHUR��
U��Qfor use when developing Device Drivers for the Next RISC Workstation (NRW). This mwUCUR��
U�k\develeopment environment is collectively referred to as the �driverkit�. It is assumed that �e�U>UR��
U
        !           214: aRthe reader is somewhat familiar with the architecture of the NRW and with the NRW �U9UR��
UZSystem Specification, particularly the sections of the specification dealing with the I/O �U4UR��
U1WSubsystem. This document contains no descriptions of any hardware features of the NRW. ���U/UR��
UUTSIt is also assumed that the reader is familiar with the Mach Operating System API, &(t�U*UR��@
UoeGspecifically, the Mach Message mechanism and the Mach Port primitive. 
        !           215: ���U%UR�� q
U�ZIn the future, portions of this document will also apply to the development of User-level �U UR��q
U\device drivers for the m68k product line; Kernel support for such drivers will probably not so�UUR��q
U eZbe available for such drivers until the 4.0 Software release (at least). This document is �UUR��@q
UtiQcurrently intended to be used by developers working on the 3.1 Software release.
        !           216: r&.�g��UT`#
[ve Overview
        !           217: s&IU
UR�� -
UU>\There are three significant features in the NRW system which are of interest for developers e &VUUR��@-
Uof device drivers:
        !           218: ati&pUUR�� r
UheONRW device drivers can run in User space as normal, non-privileged Unix tasks. em.&}T�UR��r
UtaMDevice drivers in previous NeXT machines had to run in the Kernel, either as T&�T�UR��r
UedTstandard parts of the release version of the Kernel, or as loadable Kernel servers. oe&�T�UR��r
Ue UThe primary feature which makes this possible is that each device�s registers reside t&�T�UR��r
UhiSon separate pages in the physical memory map - i.e., all of the SCSI registers are ice&�T�UR��r
U68Von one page, all of the Ethernet registers are on another page, etc. Kernel functions &�T�UR��r
U sRare provided to allow drivers to map in the single page containing their device�s &�T�UR��@r
Uy ,registers into the driver�s address space. 
        !           219: he&�T�UR�� p
UasPNRW device drivers are written in Objective C. A set of standard device classes an&�T�UR��p
UNRR(IODevice, DiskObject, LogicalDisk, NetDriver) has been written to facilitate the &�T�UR��p
U��Rdevelopment of drivers with reasonably uniform APIs and internal structures. This T�UR��p
U��Valso allows code which is common to all drivers - or a set of drivers - to be written T�UR��@p
Ued"once and inherited by subclasses.
        !           220: 3T�UR�� s
U oOThe old Unix way of designing device drivers, with the standard �top half� and ake@T�UR��s
U tS�bottom half� portions of the driver, has been replaced by a thread-based model in ysiMT�UR��s
U.eRwhich no code whatsoever in the drivers themselves runs with interrupts disabled. ZT�UR��s
UreRThe concept of an interrupt handler has been replaced by a mechanism in which the gT�UR��s
UthUKernel detects a hardware interrupt and notifies a driver of this event by sending a �tT�UR��@s
UheMach message to the driver. 
        !           221: ed(�C.))�ic$6�)�((I$6�'|r)
        !           222: eeURUR�� v
Uit\In the initial design of the NRW, it was intended that all device drivers would run in User  sUMUR��v
UT�dspace. For a variety of reasons, this goal was deferred until at least the 4.0 release; the initial n !UHUR��v
UedUNRW release (3.1) will contain a mixture of User level and Kernel level drivers. One  .UCUR��v
Uth\implication of this is that some number of device drivers will run in the Kernel in 3.1 and s ;U>UR��v
U tWin User space in 4.0. One goal of the design of the support software described in this mseHU9UR��v
UerXdocument was to make the transition between 3.1 and 4.0 (which involves porting drivers d UU4UR��v
Uwh[from the Kernel to User space) as easy as possible; the vast majority of the functions and is bU/UR��v
U �XObjective C classes described in this document have identical APIs in the Kernel and in oU*UR��v
Uic[User space. One library, libIO, was written specifically for the purpose of minimizing the UR|U%UR��@v
Uhe@differences between Kernel and User versions of device drivers.
        !           223: s d*�v++�ie$6�+�*re$6�#-| ia2UH������`F
\NRIODevice NRW Category
        !           224: "UOUR�� �
UUsXThese methods are all related to NRW-specific hardware registers. Some familiarity with so/UJUR���
Ue Wthe kernel DMA interface, as well as a thorough understanding of the NRW register map, ne <UEUR��@�
U o$is required in using these methods.
        !           225: isVU@UR�� 
Uv[Note that the method setDevPage: must be called to initialize to devPage instance variable  d cU;UR��
UwhZbefore any other of these methods can be used. See the section entitled �Kernel Level DMA pU6UR��@
Uv>Support� for details on how to obtain a IODevicePage pointer.
        !           226: �������`�
Irn#import <driverkit/IODevice.h>
        !           227: [Us�������`
Iar&
        !           228: l�������`
Isp@interface IODevice(NRW)
        !           229: o�������`
IUR&
        !           230: %�������`
Idi/*
        !           231: nce�������`�
Ind * Get/set hardware pointers.
        !           232: �������`�
I */
        !           233: �������`�
I;- (void)setDevicePage : (volatile IODevicePage *)devPageP;
        !           234: �������`�
I-'- (volatile IODevicePage *)devicePage;
        !           235: IO�������`�
Iy
        !           236: &
        !           237: O&������`�
ITh/*
        !           238: eth&������`�
Id - * Get pointer to external device registers.
        !           239: a&������`�
IUR */
        !           240: �&$������`�
IMA- (void *)extDeviceRegs;
        !           241: o&0������`�
Ig &
        !           242: t&<������`�
Ip,/*
        !           243: <UE&H������`�
Iis6 * Get pointer to internal device-specific registers.
        !           244: &T������`�
Ith */
        !           245: De&`������`�
Ile!- (void *)intDeviceSpecificRegs;
        !           246:  &l������`�
IUR&
        !           247: �&x������`�
Iny/* 
        !           248:  o&�������`�
In 7 * Get pointer to internal channel-specific registers.
        !           249: UR&�������`�
Ior */
        !           250:  d&�������`�
Ibt-- (void *)channelSpecific : (int)channelNum;
        !           251: n&�������`�
Iit&
        !           252: D&�������`�
I��/*
        !           253: `&�������`�
I��: * Get pointer to chan_t registers for specified channel.
        !           254: &�������`�
Idi */
        !           255: ce&�������`�
Ind4- (volatile chan_t *)channelRegs : (int)channelNum;
        !           256:  *&�������`�
I�&
        !           257: &�������`�
IeP/*
        !           258:  (v&�������`�
Ige7 * Get/set interrupt cause and mask registers, device 
        !           259: ePa�}����`�
IIOA * and channel versions. All registers read and written as ints.
        !           260: ��z����`�
Ier */
        !           261: te �w����`�
Ier7- (unsigned)channelIntrMask: (int)channelNum;
        !           262: voi,�t����`�
I
        !           263: o9-     (void)setChannelIntrMask: (int)channelNum
        !           264: �8�q����`�
Iet"    mask:(unsigned)mask;
        !           265: D�n����`�
I��8- (unsigned)channelIntrCause: (int)channelNum;
        !           266: icP�k����`�
I��:-     (void)setChannelIntrCause: (int)channelNum
        !           267: \�h����`�
Ioi#   cause:(unsigned)cause;
        !           268: isth�e����`�
I��- (unsigned)deviceIntrMask;
        !           269: �t�b����`�
Ian8-     (void)setDeviceIntrMask: (unsigned)mask;
        !           270: ����_����`�
I/*- (unsigned)deviceIntrCause;
        !           271: td,�pe--���$6�-�,�$6�+0| in0ne������`�
I��:-     (void)setDeviceIntrCause: (unsigned)cause;
        !           272: ������`N
Iru&
        !           273: c������`       
Ist/*
        !           274: dev)������`
        !           275: 
I��- * Obtain device interrupt summary register.
        !           276: s5������`
Ias */
        !           277: 
        !           278: �A������`�
Ier- (unsigned)intrSummary;
        !           279: rM������`�
Ine&
        !           280: tY������`�
Int/*
        !           281: nele������`�
I��F * Enable a DMA channel. Does a channel reset, configures appropriate
        !           282: q������`�
I@ * direction, loads first descriptor, and enables the channel. 
        !           283: ch}������`�
I@ * Kernel's IOEnqueueDma() must have been called prior to this.
        !           284: el�������`�
I:  */
        !           285: ha�������`�
I��+- (void)startDma: (int)channelNum
        !           286: ist�������`�
I��'   dir : (IODmaDirection)dir;
        !           287: ���������`�
Ioi 
        !           288: �������`�
I/*
        !           289: sig�������`�
I��  * simple DMA channel commands.
        !           290: tr�������`�
I *
        !           291: ,��������`
I * Set Disable Channel bit.
        !           292: �������`

I*/
        !           293: $�������`�
I.- (void)disableDma: (int)channelNum;
        !           294: &&������`
Iev&
        !           295: I&
������`
I (/*
        !           296: ned&������`
I��! * Set Force Buffer Advance bit.
        !           297: *&%������`
I
        !           298:  */
        !           299:  *&1������`�
Ier9- (void)forceDmaBufferAdvance: (int)channelNum;
        !           300: �&=������`
Ins&
        !           301: e&I������`
I��/*
        !           302: ��&U������`
I��  * Disable channel, then reset.
        !           303: �&a������`
IDM */
        !           304: ne&m������`�
Ire,- (void)resetDma: (int)channelNum;
        !           305: &y������`�
I&
        !           306: i&�������`�
Id /*
        !           307: es &�������`�
I��7 * Abort any pending DMA. Dequeue all enqueued frames.
        !           308: en &�������`�
Iis9 * dmaFreeFrame: will be called for each dequeued frame.
        !           309: i&�������`�
I: */
        !           310: ch&�������`�
I��,- (void)abortDma: (int)channelNum;
        !           311: n)&�������`�
I��&
        !           312: �&�������`�
I��/*
        !           313: `�&�������`�
I��< * To be optionally implemented by subclass; this is called
        !           314: �&�������`
I�� * as a result of dmaAbort:.
        !           315: a&�������`�
I�� */
        !           316: 
&�������`�
I��1- (void)freeDmaFrame: (unsigned)dma_id;
        !           317: n     �}����`�
I��&
        !           318: �z����`�
I��/*
        !           319: I (!�w����`�
I��, * Flush messages queued at specified port.
        !           320: ��-�t����`�
I * */
        !           321: ��9�q����`�
I- )- (void)flushIntrMsgs: (port_t)IOPort;
        !           322: cH��X&�
        !           323: .�2
        !           324: eH��X&�
        !           325: v *������h
_thyNRW Device Driver Guide    &/83&0 of &584&6                          &79/24/91&8       COMPANY CONFIDENTIAL
        !           326: � ������`
_��&�d/� *00�. $6�0�/��$6�-3| c%fo������`�
\amStandard data types
        !           327: :"UOUR��`�
U��6The IODevice class introduces one standard data type:
        !           328: :������`d
I��typedef int IOReturn;
        !           329: UUGUR�� c
U��ZThis is a standard return value for methods which perform I/O. It�s analogous to the Unix bUBUR��c
Uf Rerrno. Common values for IOReturn are defined in <driverkit/deviceCommon.h>. Each oU=UR��@c
U)dUsubclass is free to define its device-specific IOReturn values in addition to these.
        !           330: u�U8UR��`�
\ a#General Get/Set Parameters methods
        !           331: I *�U3UR�� �
U��YThese four IODevice methods (getParameter{int,char}, setParameter{int,char}) are used in �U.UR���
URconjunction with four similarly named RPCs implemented by the kernel to provide a �U)UR���
U  [general, extensible means of accessing, from user programs, device-specific parameters for �U$UR���
UWdrivers which reside in the kernel. The main reason for this mechanism is to provide a �UUR���
UWstandard way of gathering run-time statistics of drivers which reside in the kernel by e c�UUR���
Ue ZApplications running in User space. The basic requirement of this type of operation is to �UUR���
Un \allow the definition of name/value pairs in a device-specific manner and to allow access to om�UUR���
Uet[the data so defined in a uniform manner from user level. When the driverkit functionalitry  de&UUR���
Uec`resides in a shlib (instead of in a separate archive, as it currently does), this functionality ds&UUR��@�
U�/will also be provided for user-level drivers. 
        !           332: nt,&2U&UR��`�
Ur{4The general scheme of this mechanism is as follows:
        !           333: io<�UR�� �
UrlWParameters are either arrays of integers or arrays of chars. The minimum of size of an ibl&YT�UR���
UngLa parameter array is one element. The maximum size of a parameters array is dr&fT�UR��@�
U i;IO_MAX_PARAMETER_ARRAY, a system constant (currently 512).
        !           334: e a&�T�UR��`�
U�>Parameters are addressed (named) via human-readable strings. 
        !           335: &�T�UR�� �
U kVAny subclass of IODevice can define any get/set parameters it wishes. Any class which &�T�UR���
Uf Odoes so must implement the appropriate method by which the parameter(s) can be  a &�T�UR���
UnnWaccessed (getParameterInt, setParameterChar, etc.). If such a method is invoked with a  fr&�T�UR���
Un UparemeterName argument which the class does not recognize, the method call is passed  &�T�UR���
U, Mup to super. If no classes recognize the parameterName, IODevice will return p&�T�UR��@�
UevIO_DR_INVALID.
        !           336: 2U&&�T�UR�� �
UThQThe IODevice class in the kernel maintains a list which maps global unit numbers sT�UR���
U oV(IOUnitNumber) to id�s. An entry is added to this list when IODevice�s registerDevice T�UR���
U�Vmthods is called. An entry is deleted from this list when unregisterDevice is called. T�UR��@�
U c&Each entry has a unique IOUnitNumber.
        !           337: 6T�UR�� �
UrsOAny user program with root privileges can obtain the IOUnitName and IOUnitType claCT�UR���
U dZstrings of any instance of any driver in the kernel via the IOInquire() RPC. The instance PT�UR���
UprX- i.e., the global unit number - is specified by a IOUnitNumber in the IOInquire() RPC. er]T�UR���
UhaY(See the section entitled �Kernel-Level Driver Support� for detailed information on this tjT�UR��@�
Uoeand other related RPCs).
        !           338:  d1�, 33�la$6�2�.IO$6�z IO&VAURUR��`
U��&�$6�3�1rn$6�0=| n3 sURUR�� +
U oRAlternately, the IOUnitNumber and IOUnitType can be obtained if the IOUnitName is UMUR��@+
U�)known. This is performed via IOLookup().
        !           339:  .UHUR�� �
Un ROnce a user program has determined the IOUnitNumber of a desired instance, it can ;UCUR���
U�Vuse the RPCs listed below to get or set device-specific parameters. Once again, these HU>UR���
U dSRCPs are provided by the kernel. The kernel�s DMA server works in conjunction with staUU9UR���
U�RIODevice to map an IOUnitNumber tothe id of the appropriate object. The pertinent bU4UR��@�
UUR@RPCs are listed below along with the methods to which they map:
        !           340: rtz������`�
Ior
        !           341: This RPC:
        !           342: �������`�
I�&
        !           343: e�������`�
Id "IODeviceReturn IOGetParameterInt(
        !           344: �������`�
I3port_t device_master,
        !           345: ��������`�
IIOIOUnitNumber unit,
        !           346: �������`�
IIO IOParameterName parameterName,
        !           347: �������`�
Iunsigned int maxCount,
        !           348: �������`�
I;unsigned int *parameterArray,     // data returned here
        !           349: Num�������`�
I c;unsigned int *returnedCount);     // size returned here
        !           350: wn.�������`�
I v&
        !           351: I�������`�
IUR
....Maps to:
        !           352: n�������`�
Iha&
        !           353: e&
        !           354: ������`�
ItN;    getParameterInt:maxCount:parameterArray:returnedCount:
        !           355:  th&������`�
Iw &
        !           356: g&"������`�
Ipe
        !           357: This RPC:
        !           358: &.������`�
Ith&
        !           359:  &:������`�
I d#IODeviceReturn IOGetParameterChar(
        !           360: e k&F������`�
I wport_t device_master,
        !           361: sta&R������`�
I�IOUnitNumber unit,
        !           362: OU&^������`�
I o IOParameterName parameterName,
        !           363: in&j������`�
I�unsigned int maxCount,
        !           364: w &v������`�
Iho=unsigned char *parameterArray,        // data returned here
        !           365: �&�������`�
I��=unsigned int *returnedCount);         // size returned here
        !           366: �&�������`�
Ide&
        !           367: e&�������`�
I��
....Maps to:
        !           368: I&�������`�
I&
        !           369: �&�������`�
II<    getParemeterChar:maxCount:parameterArray:returnedCount:
        !           370: d &�������`�
I��&
        !           371: �&�������`�
Iig
        !           372: This RPC:
        !           373: &�������`�
I/&
        !           374: a&�������`�
Ium"IODeviceReturn IOSetParameterInt(
        !           375: &��~����`�
I  port_t device_master,
        !           376: wn.&��{����`�
I vIOUnitNumber unit,
        !           377: UR�x����`�
I�� IOParameterName parameterName,
        !           378: ��u����`�
Ietunsigned int count,      
        !           379: �r����`�
I�� unsigned int *parameterArray);
        !           380: �*�o����`�
I��&
        !           381: �6�l����`�
I��...Maps to:
        !           382:  dB�i����`�
IOG&
        !           383: aN�f����`�
I��+    setParameterInt:count:parameterArray::
        !           384: R��Z�c����`�
II&
        !           385: if�`����`�
I��
        !           386: This RPC:
        !           387: r�]����`�
INa&
        !           388: p~�Z����`�
I��#IODeviceReturn IOSetParameterChar(
        !           389: untd4�d 55�  $6�5�4��$6�%|);  
UT
UT��`b
`he&
        !           390: �eUR
UT��`o
`de&
        !           391: e�UP
UT��`
`��"NRW Device Driver Developer Guide
        !           392: &UL  UR��`+
K�Author: Doug Mitchell 
        !           393: r:m&.UG       UR��h 
Krr&<9/24/91&=
        !           394: d &OUD
UT��`-
`��&
        !           395: �d6���78���$6�7�86OS$6�} t_&ceURUR��`
U��&�H��X&�
        !           396: 8�76�xH��X&�
        !           397: ~ er�������hg
_et�                                NRW Device Driver Specification    &-#&. of &278&3                          &49/10/91&;       CONFIDENTIAL
        !           398: � ������`i
_�f&
        !           399: �+������`
_se&rd9���:;�
        !           400: i$6�:�;9�]$6�y IO&ReURUR��`
UrC&(H��X&�
        !           401: ;�:9H��X&�
        !           402: { ������h!
_xNRW Device Driver Guide    &9#&: of &A78&B                          &C9/10/91&D       COMPANY CONFIDENTIAL
        !           403: ce ������`l
_Gu&
        !           404: 
        !           405: +������`
_�&ud<���==�&=$6�=�<$6�3?|��������`�
I�port_t device_master,
        !           406: ������`�
IIOUnitNumber unit,
        !           407: UR������`�
I� IOParameterName parameterName,
        !           408: �x)������`�
Iunsigned int count,      
        !           409: 5������`�
Iet unsigned int *parameterArray);
        !           410:  NA������`�
Ipe&
        !           411: iM������`�
I ...Maps to:
        !           412:   Y������`�
I  &
        !           413:  e������`�
I  ,    setParameterChar:count:parameterArray::
        !           414: ��q������`�
I&
        !           415: }������ �
UPSee the section entitled �Code Examples� for an illustration on the use of this �������@�
Umechanism. 
I 
        !           416: Rd>�??�$6�?�>$6�=A| ce2r ����UT`%
[ o
IODiskDevice
        !           417:  #UNUR�� B
U  aThis section to be written later. All of the drivers for 3.1 which will use the DiskObject class 0UIUR��@B
U;and it subclass LogicalDisk have already been implemented.
        !           418: <JUDUR��`m
U0For reference, here�s the DiskObject interface:
        !           419: ��b������`o
Ide#ifdef KERNEL
        !           420: n������`p
I&
        !           421: Iz������`q
I�/*
        !           422: ���������`r
Iar5 * The Unix-level code associated with a particular 
        !           423: g�������`s
I  3 * subclass of DiskObject keeps an array of these 
        !           424: ay)�������`H
I�1 * to allow mapping from a dev_t to a DiskObject
        !           425: ��������`t
I��6 * id. One per Unix unit (a unit is a physical disk).
        !           426: �������`u
I�� */
        !           427: �������`v
I�typedef struct {
        !           428: o�������`w
Ixa2id rawDevId;      // LogicalDisk for raw device
        !           429: �������`x
ImeFid livePartId;    // DiskObject/SCSIDisk (etc.) for live partition
        !           430: �������`y
I)id blockId[NPART];// for block devices
        !           431: �������`z
Ice/dev_t rawDev;     // used by volCheck logic
        !           432: UR�������`{
I sdev_t blockDev;   // ditto
        !           433: &
        !           434: ������`|
I 3} IODevToIdMap;
        !           435: th&������`}
I &
        !           436: I&"������`~
Ian#endif KERNEL
        !           437: &.������`
Iea&
        !           438: b&:������`�
I/*
        !           439: UR&F������`�
Ire& * Basic �usefulness� state of drive.
        !           440: &R������`�
Io */
        !           441: #i&^������`�
I��typedef enum {
        !           442: z��&j������`�
I�5IO_RS_READY,          // Ready for r/w operations
        !           443: a&v������`�
Ila<IO_RS_NOTREADY,       // not ready (spinning up or busy)
        !           444: rr&�������`�
I��,IO_RS_NODISK,         // no disk present
        !           445: ev&�������`�
I
        !           446: �.IO_RS_EJECTING        // eject in progress
        !           447: &�������`�
Ial} DiskReadyState;
        !           448: &�������`�
I��&
        !           449: �&�������`�
Ide!@interface IODiskDevice:IODevice
        !           450: i&�������`�
I//{
        !           451: &�������`$
Iev  @private
        !           452: �&�������`%
Ili&
        !           453: a&�������`�
IOb8id       _logicalDisk;     // first LogicalDisk object
        !           454: &�������`�
IT]-         // attached to this raw disk.
        !           455: d&�������`�
I /         // May be nil. 
        !           456: ��������`�
I_t)u_int    _blockSize;       // in bytes 
        !           457: 3�����`�
Ith/u_int    _deviceSize;      // in blockSize's 
        !           458: dif�|����`�
I��7unsigned _removable:1,     // removable media device 
        !           459: Ire*�y����`�
Ine1         _formatted:1,     // disk is formatted
        !           460: �6�v����`�
Ity         _diskIsOpen:1,
        !           461: �B�s����`�
IEA:         _isPhysDevice:1;  // this is NOT a logical disk
        !           462: N�p����`I
IAD&
        !           463: Z�m����`�
Iy #ifdef KERNEL
        !           464: f�j����`�
I��4IODevToIdMap *idMapArray; // provides dev_t to id 
        !           465: evr�g����`�
I
        !           466: �.        // mapping. The array itself is
        !           467: ~�d����`�
Ial-        // statically allocated by the
        !           468: �d@�kDAA���$6�A�@ev$6�?C| ��6�������`�
Iog-        // Unix portion of the driver.
        !           469: �������`�
I#endif KERNEL
        !           470: ������`�
Iaw.id_LogicalDiskLock;  // NXLock. Serializes
        !           471: )������`�
I��*        // operations which change 
        !           472: 5������`�
I�+        // LogicalDisks attached to 
        !           473:  //A������`�
Iif        // this device.
        !           474: M������`�
I//7char_driveName[MAXDNMLEN];// for Unix 'drive_info'
        !           475:    Y������`�
I//        // requests 
        !           476: ��e������`�
I  
        !           477: en:q������`�
I�/*
        !           478:  }������`�
Iic3 * The lastReadyState variable is initialized by 
        !           479: IAD�������`�
I�3 * device-specific subclass, but is subsequently 
        !           480: ap �������`J
Iov) * only changed by the volCheck module.
        !           481: �������`�
Ipi */
        !           482:  �������`�
I�d!DiskReadyState _lastReadyState;
        !           483: s�������`\
Id &
        !           484: t�������`^
I/*
        !           485: �������`_
I' * Statistics. Accessed en masse via 
        !           486: @�������``
I' * getParameterInt(DISK_STATS_ARRAY).
        !           487: ���������`a
I */
        !           488:  �������`b
In unsigned       _readOps;
        !           489: &&������`c
IERunsigned       _bytesRead;
        !           490: _&
������`d
I//,unsigned       _timeReading;      // in ms
        !           491: &������`e
Ionunsigned       _writeOps;
        !           492: `�&%������`f
I  unsigned       _bytesWritten;
        !           493: A��&1������`g
Iunsigned       _timeWriting;
        !           494: &=������`h
Ic1struct tsval   _startOp;          // private...
        !           495: '&I������`]
I�&
        !           496: /&U������`�
I r}
        !           497: &a������`�
I��&
        !           498: �&m������`�
I��/*
        !           499: ��&y������`�
I��# * Register insertion notify port.
        !           500: ate&�������`�
Ial */
        !           501: y &�������`�
I�6- (IOReturn) insertNotify  : (port_name_t)notifyPort
        !           502: &�������`�
IJ-     ownerPort : (port_name_t)ownerPort;
        !           503: &�������`�
Ipi&
        !           504:  &�������`�
I�/*
        !           505: !D&�������`�
ItR3 * Public methods to get and set disk parameters. 
        !           506: I&�������`�
I��3 * These are implemented in the DiskObject class. 
        !           507: ���&�������`�
I  */
        !           508: ar&�������`�
ITS- (unsigned)deviceSize;
        !           509: a&�������`�
I��- (unsigned)blockSize;
        !           510:    &�������`�
I��4- (IOReturn)setFormatted    : (u_int)formattedFlag;
        !           511: ��    �}����`�
Id - (unsigned)formatted;
        !           512: // �z����`�
I��- (unsigned)removable;
        !           513:  _w!�w����`�
I��- (const char *)driveName;
        !           514:  _b-�t����`�
I��- (unsigned)isPhysDevice;
        !           515: 9�q����`�
I;
        !           516: - (unsigned)diskIsOpen;
        !           517: ucE�n����`�
I; &
        !           518:  Q�k����`�
I
        !           519: '/*
        !           520: ��]�h����`�
I��' * Public 'Eject current disk' method.
        !           521: &
        !           522: �i�e����`�
I�� */
        !           523: ��u�b����`�
I��- (IOReturn) ejectDisk;
        !           524: ti��_����`�
I��
        !           525: dB��CC�ot$6�C�B��$6�AF| rt6t)������`�
I��&
        !           526: �������`�
I��/*
        !           527: `�������`�
I��7 * These methods must be implemented by each subclass.
        !           528: ete)������`�
I�� */
        !           529: ��5������`K
Ile&
        !           530: tA������`�
Ict/*
        !           531: s. M������`�
I�8 * Determine basic state of device. This method should 
        !           532: aY������`�
I��2 * NOT implement any retries. It also should not 
        !           533: e������`L
Itt2 * return IO_RS_EJECTING (That's only used in the
        !           534: q������`�
Iat& * lastReadyState instance variable).
        !           535: }������`�
I�w */
        !           536: ���������`�
I c- (DiskReadyState)checkReady;
        !           537: �������`�
Ine&
        !           538: s�������`�
I��/*
        !           539: `��������`�
Idi" * Device-specific eject command.
        !           540: �������`�
I
        !           541: ' */
        !           542: ���������`�
I��- (IOReturn)devEjectDisk;
        !           543: �������`�
I�e&
        !           544: ��������`�
I�/*
        !           545: ���������`�
IOR9 * Get physical parameters (dev_size, block_size, etc.) 
        !           546: �������`M
I� * from new disk. Called 
        !           547: &&������`�
I" * upon disk insertion detection.
        !           548: &
������`�
Irt */
        !           549: t)&������`�
I��- (IOReturn)getPhysParams;
        !           550: `�&%������`�
I��&
        !           551: *&1������`�
It /*
        !           552: ple&=������`�
Icl9 * Called by volCheck thread when WS has told us that a 
        !           553: t&I������`�
Ict6 * requested disk is not present. Pending I/Os which 
        !           554: &U������`�
Iho1 * require a disk to be present must be aborted.
        !           555: a&a������`�
Io  */
        !           556:  n&m������`�
IL- (void)abortRequest;
        !           557: &y������`�
Iy &
        !           558: d&�������`�
I��/*
        !           559: Iat&�������`�
Ie 7 * Called by the volCheck thread when a transition to 
        !           560: ��&�������`�
Iea; * �ready� is detected. Pending I/Os which require a disk 
        !           561: I��&�������`N
I�� * may proceed.
        !           562: e-&�������`�
Ima */
        !           563: ��&�������`�
I *- (void)diskPresent;
        !           564: �&�������`�
Ije&
        !           565: i&�������`�
I�/*
        !           566: &
        !           567: �&�������`�
I�8 * Inquire if disk is present; if not, and 'prompt' is 
        !           568: de&�������`�
I, , * YES, ask for it. Returns IO_R_NODISK if:
        !           569: . &�������`�
I��6 *    prompt YES, disk not present, and user cancels 
        !           570:       �}����`O
I�� * request for disk.
        !           571: ur�z����`�
I�# *    prompt NO, disk not present.
        !           572: `�!�w����`�
I�� * Else returns IO_R_SUCCESS.
        !           573: -�t����`�
I h */
        !           574: d 9�q����`�
I��*- (IOReturn)isDiskPresent: (BOOL)prompt;
        !           575: E�n����`�
Ihi&
        !           576: 
        !           577: Q�k����`�
Iho/*
        !           578: req]�h����`�
Ipr$ * Standard DiskObject I/O methods.
        !           579: �i�e����`�
I�� */
        !           580: �u�b����`�
ItR&- (IOReturn) readAt: (u_int)offset 
        !           581: ��_����`�
Iat  length : (u_int)length 
        !           582: dD�siFF���dE�PePR�re$6�F�D *$6�CH| ��6��������`�
Ioi  buffer : (void *)buffer
        !           583: ������`�
I��;  actualLength : (u_int *)actualLength; /* returned */
        !           584: res������`�
Ipr 
        !           585: )������`�
I�(- (IOReturn) readAsync: (u_int)offset 
        !           586: IS5������`�
I��  length : (u_int)length 
        !           587: A������`�
Ius  buffer : (void *)buffer
        !           588: M������`�
Ir !  pending : (void *)pending;
        !           589:  Y������`�
It  
        !           590: e������`�
I�%- (IOReturn) write: (u_int)offset 
        !           591: tq������`�
I *  length : (u_int)length 
        !           592: }������`�
It  buffer : (void *)buffer
        !           593: �������`�
I��;  actualLength : (u_int *)actualLength; /* returned */
        !           594: I/O�������`&
I�� 
        !           595: I���������`
I��)- (IOReturn) writeAsync: (u_int)offset 
        !           596: s�������`
I�  length : (u_int)length 
        !           597: �������`
I  buffer : (void *)buffer
        !           598: �������`
I!  pending : (void *)pending;
        !           599: �������`
I 
        !           600: �������`
I&
        !           601: *�������`       
I/*
        !           602: �������`
        !           603: 
I * Private methods.
        !           604: oi&&������`
Ivo */
        !           605: uf&
������`
I�&
        !           606: �&������`

Ith/*
        !           607: _in&%������`
I/*+ * Register a connection with LogicalDisk.
        !           608: )��&1������`
I-  */
        !           609: ur&=������`
Iin'- (void) registerLogicalDisk: diskId;
        !           610: eng&I������`
I 
        !           611: &
        !           612: �&U������`
I/*
        !           613: uff&a������`
Ir
        !           614: < * Implemented by DiskObject class, invoked by instance of 
        !           615: ��&m������`
I 
        !           616: 7 * subclass upon completion of device initialization. 
        !           617:  
        !           618: t&y������`
I *8 * Handles communication with LogicalDisk, polling for 
        !           619:   &�������`�
Iuf * disk insertion, etc.
        !           620: &�������`
I ( */
        !           621: *)&�������`
Iet- (void)registerDisk;
        !           622: &�������`
I��&
        !           623: �&�������`
I- /*
        !           624: tur&�������`
I_i * Private Get/set methods.
        !           625: �&�������`
Iu_ */
        !           626: ng&�������`
I.- (void)setDeviceSize       : (unsigned)size;
        !           627: &�������`
Ind.- (void)setBlockSize        : (unsigned)size;
        !           628: &�������`
I4- (void)setIsPhysDevice     : (unsigned)isPhysFlag;
        !           629: &�������`
Ids- getLogicalDisk;
        !           630:       �}����` 
I��7- (void)setRemovable        : (unsigned)removableFlag;
        !           631: `�z����`!
Ia 2- (void)setDriveName        : (const char *)name;
        !           632: !�w����`"
I��%- (DiskReadyState)getLastReadyState;
        !           633: :-�t����`#
I��:- (void)setLastReadyState   : (DiskReadyState)readyState;
        !           634: 9�q����`$
Ied4- (void)setDiskIsOpen       : (unsigned)isOpenFlag;
        !           635: ��E�n����`%
Iub&
        !           636: sQ�k����`f
Iof/*
        !           637: ce ]�h����`g
I
        !           638: t * Statistics support.
        !           639: Hani�e����`h
I w *
        !           640: ogiu�b����`i
Ior: * These four methods are invoked by subclass during I/O.
        !           641: ��_����`j
I*) */
        !           642: ��dG�;
        !           643: HH�
        !           644: �$6�H�G��$6�FJ| �1��������`k
Ing- (void)startRead;
        !           645: .- ������`l
Ie 5- (void)endRead             : (int)bytesTransferred;
        !           646: e������`@
I: - (void)startWrite;
        !           647: ��)������`B
Ioi5- (void)endWrite            : (int)bytesTransferred;
        !           648: �5������`C
ItL&
        !           649: cA������`D
I��/*
        !           650: I��M������`E
Iab( * For gathering cumulative statistics.
        !           651: �zY������`F
I-  */
        !           652: see������`G
I: C- (IODeviceReturn)getParameterInt : (IOParameterName)parameterName
        !           653: adyq������`H
I��)   maxCount : (unsigned int)maxCount
        !           654: s}������`I
Ita   parameterArray : 
        !           655:  �������`J
In (   (unsigned int *)parameterArray
        !           656: ���������`K
I��   returnedCount : 
        !           657: ���������`L
Ita(   (unsigned int *)returnedCount;
        !           658:  *�������`M
Ii
        !           659: �������`N
Is 0#define DISK_STATS_ARRAY   "IO_Disk_Statistics"
        !           660: j�������`O
I&
        !           661: �������`P
I/*
        !           662: �������`Q
I
        !           663: �G * Indices into array obtained via getParameterInt : DISK_STATS_ARRAY.
        !           664: �������`R
I�� */
        !           665: k�������`S
ItR'#define DISK_STATS_READ_OPS        (0)
        !           666: Rea&&������`T
Int'#define DISK_STATS_BYTES_READ      (1)
        !           667: - &
������`U
I��'#define DISK_STATS_TIME_READING    (2)
        !           668:    &������`V
ITr'#define DISK_STATS_WRITE_OPS       (3)
        !           669: ��&%������`W
I��'#define DISK_STATS_BYTES_WRITTEN   (4)
        !           670: mul&1������`X
I�z'#define DISK_STATS_TIME_WRITING    (5)
        !           671: `G&=������`Y
Iet'#define DISK_STATS_ARRAY_SIZE      (6)
        !           672: ram&I������`Z
I��&
        !           673: �&U������`[
Iax/*
        !           674:  : &a������`e
Iou&
        !           675: s&m������`&
Ita/*
        !           676:   &y������`'
I
        !           677:  < * internal setFormatted - avoids logical disk interaction.
        !           678: ��&�������`(
I�� */
        !           679:   &�������`)
I��,- (void)setFormattedInt:(int)formattedFlag;
        !           680: )r&�������`*
I��&
        !           681: �&�������`+
I
        !           682: /*
        !           683: ��&�������`,
Iin9 * Lock/Unlock device for LogicalDisk-specific methods. 
        !           684: O&�������`-
I��< * Invoked only by LogicalDisks which are attached to this 
        !           685: ta&�������`�
Ite * device.
        !           686: TAT&�������`.
I�� */
        !           687: R&�������`/
I��- (void)lockLogical;
        !           688: I&�������`0
I  - (void)unlockLogical;
        !           689: `T&�������`1
I_S&
        !           690: S     �}����`2
I1)#ifdef KERNEL
        !           691: �z����`3
IDI&
        !           692: S!�w����`4
I  - (IODevToIdMap *)getIdMap;
        !           693: #d-�t����`5
IRI*- (void)setIdMap : (IODevToIdMap *)idMap;
        !           694: 9�q����`6
IYT&
        !           695: WE�n����`7
I�#endif KERNEL
        !           696: dI�  JJ�Y$6�J�IE $6�HL| ��[������`8
I��
        !           697: ou������`9
I&/*
        !           698: /*������`:
I'8 * Convert an IOReturn to text. Overrides superclass's 
        !           699: ac)������`;
I��; * method of same name to allow for additional IOReturn's 
        !           700: :(i5������`
I)r * defined in DiskObject.h.
        !           701: ��A������`<
I�� */
        !           702: ��M������`=
Ioc2- (const char *)IOReturnToString : (IOReturn)rtn;
        !           703: Y������`>
I��&
        !           704: *e������`?
Iog@end
        !           705: kq������`@
Ied&
        !           706:  }������`A
I��/*
        !           707: Ite�������`B
I��& * IOReturn's specific to DiskObject.
        !           708: �������`C
ILo */
        !           709: 
        !           710: I�������`D
I  B#define IO_R_NOLABEL         (-1100)       /* no label present */
        !           711: �������`E
IL
        !           712: D#define IO_R_UNFORMATTED     (-1101)       /* disk not formatted */
        !           713: ap�������`F
I5B#define IO_R_NODISK          (-1102)       /* disk not present */
        !           714: �������`G
I7&
        !           715: �dK��LL�$6�L�K�$6�JN| '����UT`*
[��IONetDevice
        !           716: ��#UNUR�� 
U��WThe IONetDevice class is basically just an Objective C layer which sits underneath the cla0UIUR��
U��^existing kernel netif interface. Implementing netif-type protocols in User space is not going =UDUR��@
Uje$to be possible until at least 4.0. 
        !           717: ��WU?UR�� 

U- UThe NetDriver module consists of the IONetDevice class and the NetDriverKern module. ?dU:UR��

U��ONetwork drivers (e.g., the Ethernet driver) are subclasses of IONetDevice. The pecqU5UR��

U.
        !           718: SNetDriverKern module converts netif �C� calls (e.g., a netif�s if_output_func_t or )  ~U0UR��

UreSif_getbuf_func_t) into IONetDevice method calls. The relationship between what the for�U+UR��@

U��^kernel sees as a netif module and an actual instance of a IONetDevice subclass is as follows:
        !           719: �U&UR��`
UQthe if_private data of the netif is the id of the IONetDevice subclass instance.
        !           720: ��U!UR��`
UHThe IONetDevice class contains a netif pointer as an instance variable.
        !           721: UR�UUR�� 
UIOSAt initialization time, the driver (i.e., the IONetDevice subclass instance) calls 0UI�UUR��
Uex\if_attach() in the normal fashion; all of the function pointers registered in this call are UD�UUR��@
Utofunctions in NetDriverKern.
        !           722: 0.&
U
UR�� 
U
XWhen one of the functions in NetDriverKern is called; the netif pointer is converted to  ?&UUR��
U��Pan id via if_private() and the appropriate method is invoked in the IONetDevice ec&'UUR��@
U.
        !           723: subclass instance.
        !           724: e c&AT�UR�� 
Uca^The actual functionality provided by the IONetDevice class itself is minimal; it exists along &NT�UR��
U TVwith the NetDriverKern module to provide a common way for an IODevice-based driver to &[T�UR��@
Uan(work with the standard netif interface.
        !           725: :
        !           726: &������� 
\& h&�������@
\ofIONetDevice Interface
        !           727: &�T�UR��`
\bc&
        !           728: s&�������`
IUR#import <driverkit/IODevice.h>
        !           729: ss &�������`B
Ioi#import <net/netif.h>
        !           730: &�������`C
I��&
        !           731: &�������`A
Iat @interface IONetDevice:IODevice
        !           732: Ne������`
Ins{
        !           733: ������`&
IUR  @private
        !           734: x�~����`'
Ihe&
        !           735: r$�{����`
If netif_t _netif;
        !           736: r0�x����`
Iis}
        !           737: <�u����`
I��&
        !           738: H�r����` 
I N/*
        !           739: verT�o����`!
I��: * Get/set netif pointer for use with normal netif calls.
        !           740: `�l����`"
Ite */
        !           741: onl�i����`#
IUR#- (void)setNetif: (netif_t)Netif;
        !           742: andx�f����`$
Iet- (netif_t)getNetif;
        !           743: O��c����`%
IUR&
        !           744: �dM�T�NN�ac$6�N�M I$6�LQ| st0g ������`&
I T/*
        !           745: h t������`'
IodD * Increment packet, error, and collision counts (accessed here via
        !           746: ��������`(
Ih H * if_ipackets(), etc.). These are typically used only internally by a 
        !           747: of)������`)
Irf * IONetDevice subclass.
        !           748: s5������`*
IUR */
        !           749: orA������`+
Iic- (void)incrInPackets;
        !           750: IoiM������`,
Iif- (void)incrOutPackets;
        !           751: 
        !           752: Y������`-
Iat- (void)incrInErrors;
        !           753: e������`.
I��- (void)incrOutErrors;
        !           754: ��q������`/
I
        !           755: x- (void)incrCollisions;
        !           756: �{}������`0
In&
        !           757: f�������`1
I��/*
        !           758: `�������`2
I��= * Methods to be implemented by subclass. These methods are 
        !           759: *�������`3
Int; * invoked by the NetDriverKern module; they're basically 
        !           760: 
        !           761: on�������`D
IUR * just an Objective C layer 
        !           762: �������`4
I��, * underneath the kernel's netif interface.
        !           763: %�������`5
I */
        !           764: ��������`6
I- (int)netInit;
        !           765: ac�������`7
I�(- (int)netInput   : (netif_t)realNetif 
        !           766: �������`8
I(                    buf : (netbuf_t)buf
        !           767: ���������`9
Ime+                    extra : (void *)extra;
        !           768: sed&&������`:
I��"- (int)netOutput : (netbuf_t)buf
        !           769: &
������`;
I�+                    addrs : (void *)addrs;
        !           770: `)&������`<
Ice- (netbuf_t)netGetBuf;
        !           771: `*&%������`=
I��+- (int)netControl  : (const char *)command
        !           772: ��&1������`>
Ioi*                     data : (void *)data;
        !           773: &=������`?
I;
        !           774:  
        !           775: &I������`@
I- @end
        !           776: n&~������`F
\��NetDriverKern Interface
        !           777: in&�T�UR�� X
U��XThe functions in this module are registered by all subclasses of IONetDevice during the le&�T�UR��X
U. `if_attach() call. The functions here just map a netif pointer to an id and forward the calls to y &�T�UR��@X
UDthe appropriate driver method.
        !           778: r 
        !           779: &�������`T
I��&
        !           780: *&�������`W
Irn #import <driverkit/NetDriver.h>
        !           781: ��&�������`U
I��#import <net/netif.h>
        !           782: &�������`V
I��&
        !           783: �&�������`G
Iet#extern int netInit(netif_t netif);
        !           784: ��������`H
I  $extern int netInput(netif_t netif, 
        !           785: ��������`I
I  netif_t realnetif,
        !           786: a ������`J
Iednetbuf_t nb, 
        !           787: I��+������`K
I void *extra);
        !           788: 
��7�}����`L
I%extern int netOutput(netif_t netif, 
        !           789: ;C�z����`M
I<netbuf_t nb, 
        !           790: )neO�w����`N
I��void *address);
        !           791: t[�t����`O
Ins*extern netbuf_t netGetBuf(netif_t netif);
        !           792: g�q����`P
I d&extern int netControl(netif_t netif, 
        !           793: s�n����`Q
I@const char *command, 
        !           794: `F�k����`R
In void *data);
        !           795: dO� tQQ�re$6�P�RE d$6� h(&. URUR��`9
U j& $6�Q�Oor$6�NT| thop
        !           796: ��
        !           797: ��UUhd
[d.2&h
ZlibIO - Kernel/User Compatibility Library
        !           798: B����UT`
[etPurpose
        !           799: ��]UMUR�� `
U��ZThis library provides a consistent API for device drivers which may have to run in Kernel jUHUR��`
U��[space at one time (or in one configuration) and in User space at another time. Using libIO tifwUCUR��`
UJZminimizes the work or porting between the two environments. libDev itself, as well as all �U>UR��`
Uif]of the NRW Kernel level drivers, were written using libIO in order to have one set of source t�U9UR��@`
UexBfiles with minimal #ifdef�s for Kernel and User mode differences.
        !           800: �U4UR�� �
UtiZFor developers who are writing User-level drivers which are known to never have to run in �U/UR���
U]the Kernel, many of these functions can be disregarded in favor of their libsys counterparts �U*UR���
UZ(e.g., malloc() instead of IOMalloc()). It is advisable to look long and hard at possible �U%UR���
U[system requirements for the next several years before making such a decision to use libsys ���U UR��@�
Uoscalls in favor of libIO calls.
        !           801: bra&�q��UT`t
[isImplementation
        !           802: ce &I������`n
\haKernel Mode
        !           803: er&dUUR�� w
U`WAll device drivers in the Kernel run in the kernel�s memory address space; any threads g l&qUUR��w
U��\which these drivers create (using IOForkThread(), see below) are threads in a �kernel task� s &~U
        !           804: UR��w
U`f- this is a task which shares the kernel�s address space but 
Vnot
U the kernel�s IPC space. Mach &�UUR��w
Ufi[RPCs are available to device drivers via the mach_user_internal mechanism; this allows for elo&�UUR��w
Ung]all of the Mach functions normally used in user space (e.g., port_allocate(), vm_allocate()) a&�T�UR��w
Uon]to be accessed in the kernel with the standard User-level API. All of the threads created by (&�T�UR��w
Ulo]all of the device drivers in the kernel run as part of one kernel task, IOTask. This task is t&�T�UR��w
Uer`created early during system initialization, before any device drivers are probed or initialized bI&�T�UR��@w
U��0(see the section entitled �Autoconfiguration�).
        !           805: ha&�T�UR��`�
\UUser Mode
U
        !           806: T�UR�� �
UrsZThe current User-level implementation of libIO provides an archive (.a) file which driver 
T�UR���
Uer]developers can link into their drivers. Each driver is a separate task, with its own copy of `T�UR��@�
U wZlibIO. After some time of development and debug, libIO will be added to the libsys shlib.
        !           807: H��X&�
        !           808: R�PEo H��X&�
        !           809: � mem;������`$
_lo`NRW Device Driver Guide    # of 18                          7/30/91       COMPANY CONFIDENTIAL
        !           810: ,  ������`m
_T�&
        !           811: R+������`>
_e &edS�rdTT�f $6�T�S��$6�QV|  kru����UT`,
[erThread Functions
        !           812: h#UNUR�� 
UUR\These functions basically provide the functionality of the cthread package in a uniform way  o0UIUR��@
UT� in both User and Kernel space. 
        !           813:  ee����UT`
[guIOForkThread()
        !           814: UR�U@UR��`B
U M Start a new thread. 
        !           815: �U;UR��`
UUs&
        !           816: l�U6UR��`3
Vn #import <driverkit/libIO.h>
        !           817: .a�U1UR��`
Ur CIOThread 
VIOForkThread(
UIOThreadFcn fcn, void *arg
V)
U;
        !           818: ive�U,UR��`A
UDESCRIPTION
        !           819:  c�U'UR�� D
U��XThis function causes a new thread to be started up in the current task�s address space. ys&U"UR��@D
UbThe thread begins execution at function 
Qfcn
U, which is passed as its argument 
Qarg
U.
        !           820: &8�s��UT`
[idIOSuspendThread()
        !           821: &VUUR��`)
U 7?Suspend the execution of a thread started with IOForkThread().
        !           822: ��&mUUR��`+
U&
        !           823: &~UUR��`<
V#import <driverkit/libIO.h>
        !           824: f &�U
        !           825: UR��`.
U�8void 
VIOSuspendThread(
UIOThread aThread
V)
U;
        !           826:  k&�UUR��`/
UUTDESCRIPTION
        !           827: ad&�UUR�� 
UURSThis function causes the execution of a running thread to pause. The thread can be age&�T�UR��@
U oresumed with IOResumeThread().
        !           828: r a�L��UT`2
[ eIOResumeThread()
        !           829: u)T�UR��`4
UURCResume the execution of a thread suspended with IOSuspendThread().
        !           830: �U6@T�UR��`7
U#i&
        !           831: rQT�UR��`8
V.h#import <driverkit/libIO.h>
        !           832: rekT�UR��`:
Ud(7void 
VIOResumeThread(
UIOThread aThread
V)
U;
        !           833: `AdU�DVV�us$6�V�Un $6�TX| URDURUR��`;
UegDESCRIPTION
        !           834: atUMUR��`=
U
UGThis function causes the execution of a suspended thread to continue. 
        !           835: uspM����UT`?
[URIOExitThread()
        !           836: penkUDUR��`@
U a/Terminate the execution of the current thread.
        !           837: ���U?UR��`C
UUR&
        !           838: ��U:UR��`E
V<d#import <driverkit/libIO.h>
        !           839: ���U5UR��`F
UI&volatile void 
VIOExitThread()
U;
        !           840: �U0UR��`G
U��DESCRIPTION
        !           841: RI�U+UR�� H
U��[This function causes the execution of the current (calling) thread to terminate. Note that age�U&UR��H
U oXthere is no way for one thread to �kill� another thread other than by sending some kind 4�U!UR��@H
UxeNof message to the soon-to-be-terminated thread instructing it to kill itself.
        !           842: &-�r��UT`0
[.hTimer Functions
        !           843: it&c�n��UT`I
[UR
        !           844: IOSleep()
        !           845: &�UUR��`J
UeT,Sleep for indicated number of milliseconds.
        !           846: &�UUR��`K
U&
        !           847: &�U
        !           848: UR��`L
V#import <driverkit/libIO.h>
        !           849: &�UUR��`M
U0void 
VIOSleep(
Uint milliseconds
V)
U;
        !           850: UR&�UUR��`N
URIDESCRIPTION
        !           851: UR&�T�UR��`O
U fSThis function causes the caller to block for the indicated number of milliseconds.
        !           852: [URT�UR�� ~
UenTThe current User level implementation of IOSleep only has a resolution of 1 second; CT�UR��~
U��Zthe indicated number of milliseconds is rounded up to the next highest integral number of (T�UR��@~
U��Tseconds. When we have a thread-safe implementation of usleep(), this will be fixed.
        !           853: e BT�UR��`P
Uth&
        !           854: ddW�URXX� n$6�X�Wth$6�VZ| 4UR����UT`Q
[es
        !           855: IODelay()
        !           856: &UNUR��`R
UteD�Wait� (without blocking) for the indicated number of microseconds.
        !           857: nc=UIUR��`S
UUT&
        !           858: INUDUR��`T
VU#import <driverkit/libIO.h>
        !           859: dihU?UR��`U
U��0void 
VIODelay(
Uint microseconds
V)
U;
        !           860: L�U:UR��`V
UveDESCRIPTION
        !           861: �U5UR��`W
U5This is a quick, non-blocking version of IOSleep(). 
        !           862: �U0UR�� X
UDE\This function only guaranteed a 
Qminimum
U �spin� delay in the User level version; due um�U+UR��X
Us.\to thread scheduling, the call to IODelay() could take much longer than the indicated time. on�U&UR��X
UT�]This should not be a problem with properly designed User level drivers as this is actually a a�U!UR��@X
UUR4common real-time constraint on all User-level code.
        !           863: em&�r��UT`Y
[()IOTimeout()
        !           864:  f&-UUR�� Z
U��IArrange for the specified function to be called at a certain time in the &:UUR��@Z
Ufuture.
        !           865: th&QUUR��`[
U&
        !           866: &bU   UR��`\
V4#import <driverkit/libIO.h>
        !           867: IO&|UUR��`]
U��Ivoid 
VIOTimeout(
UIOThreadFcn fcn, void *arg, int seconds
V)
U;
        !           868: s&�T�UR��`_
USDESCRIPTION
        !           869: UR&�T�UR�� e
Uor}This function causes function 
Qfcn
U to be called in 
Qseconds
U seconds
Q, 
Uwith 
Qarg
U as 
Qfcn
U�s O&�T�UR��e
UWTargument. The timeout request can be cancelled via IOUntimeout().The callout occurs  f&�T�UR��@e
UntOin the context of the caller�s task, but in a thread which is unique to libIO.
        !           870: X&��A��UT`f
[heIOUntimeout()
        !           871: T�UR��`j
Ud <Cancel an outstanding timeout request made via IOTimeout().
        !           872: T�1T�UR��`x
Ube&
        !           873: pBT�UR��`y
Vly#import <driverkit/libIO.h>
        !           874: s \T�UR��`z
U a>void 
VIOUntimeout(
UIOThreadFcn fcn, void *arg
V)
U;
        !           875: dY�IOZZ���$6�Z�Yd $6�X\|  tUURUR��`{
UfuDESCRIPTION
        !           876: URUMUR�� |
UU  VThis function removes a request made via IOTimeout() from the current list of pending %UHUR��|
UcnZtimeout requests. An error will be logged to the console if the specified fcn/arg pair is 2UCUR��@|
Uus(not currently registered for a callout.
        !           877: Qg����UT`�
[sIOTimeStamp()
        !           878: �U:UR��`�
Ucn2Obtains a microsecond-accurate current timestamp.
        !           879: �U5UR��`�
Uce&
        !           880: d�U0UR��`�
V.T#import <driverkit/libIO.h>
        !           881: ���U+UR��`�
Von#import <sys/time_stamp.h>
        !           882: t i�U&UR��`�
Us 4void 
VIOTimeStamp(
Ustruct tsval *ts
V)
U;
        !           883: )
        !           884: &&U!UR��`�
Ud DESCRIPTION
        !           885: ts&UUR��`1
UquLThis function obtains a quick, microsecond-accurate, system-wide timestamp.
        !           886: or&G�m��UT`6
[.hMemory Allocation Functions
        !           887:  &}�i��UT`�
[IIOMalloc()
        !           888: n, &�UUR��`�
U;
        !           889: Standard memory allocator.
        !           890: &�U
        !           891: UR��`�
U&
        !           892: &�UUR��`�
V#import <driverkit/libIO.h>
        !           893: &�UUR��`�
U\*void *
VIOMalloc(
Uint size
V)
U;
        !           894: &�T�UR��`�
UURDESCRIPTION
        !           895: ThT�UR�� �
Us ^This function causes 
Qsize
U bytes of memory to be allocated; a pointer to the memory is T�UR���
UilTreturned. No guarantees exist as to the alignment or the physical contiguity of the cu(T�UR���
UANallocated memory. The memory allocated via IOMalloc() is eventually freed via 5T�UR��@�
Ucu
        !           896: IOFree().
        !           897: d[�
        !           898: d\\�#i$6�\�[UR$6�Z^|  iUR����UT`�
[  IOFree()
        !           899: a&UNUR��`�
Ul %Free memory allocated by IOMalloc().
        !           900: E=UIUR��`�
UUR&
        !           901: �NUDUR��`�
Vct#import <driverkit/libIO.h>
        !           902: ndhU?UR��`�
Uwi0void 
VIOFree(
Uvoid *p, int size
V)
U;
        !           903: at�U:UR��`�
U�iDESCRIPTION
        !           904: I�U5UR�� }
UUUThis function frees memory allocated by IOMalloc(). Unlike the standard User version ��U0UR��}
Uve^of free(), the 
Qsize
U argument is required here to have a consistent API between Kernel �U+UR��@}
UThand User versions.
        !           905: ^Th�|��UT`^
[ Miscellaneous Functions
        !           906: y &�x��UT`�
[ pIOLog()
        !           907: th&<UUR��`�
UURLog a string to the console.
        !           908: a&SUUR��`�
Uth&
        !           909: l&dUUR��`�
Vsi#import <driverkit/libIO.h>
        !           910: UR&~UUR��`�
Uca5void 
VIOLog(
Uconst char *format, ...
V)
U;
        !           911: t&�U
        !           912: UR��`�
UT�DESCRIPTION
        !           913: cu&�UUR�� �
UXThis is the standard way of logging a string to the console. The arguments are stdargs, &�UUR��@�
Ujust like printf.
        !           914: &�Q��UT`�
[UTIOVmTaskSelf()
        !           915: )
        !           916: aT�UR��`�
Ul *Obtain the vm_task_t of the current task.
        !           917: &T�UR��`�
U
        !           918: �&
        !           919: D7T�UR��`�
V#i#import <driverkit/libIO.h>
        !           920: U?QT�UR��`�
Uvo"vm_task_t 
VIOVmTaskSelf()
U;
        !           921: d]�DE^^���$6�^�]ry$6�\`| ar vURUR��`�
U��DESCRIPTION
        !           922: reUMUR�� �
U
UWThis is used to obtain the current task�s vm_task_t. This function is required because an%UHUR���
UThYthe typedef of vm_task_t is a vm_map_t inside the Kernel and basically a port_t (i.e., a �2UCUR��@�
Uritask_t) in User space. 
        !           923: URg����UT`�
[U
        !           924: IOPanic()
        !           925: �U:UR��`�
Uve>Panic or dump core, logging a �reason� string to the console.
        !           926: �U5UR��`�
UV&
        !           927: U�U0UR��`�
V�#import <driverkit/libIO.h>
        !           928: ���U+UR��`�
Uth@volatile void 
VIOPanic(
Uconst char *format, ...
V)
U;
        !           929: re�U&UR��`�
UURDESCRIPTION
        !           930: ju�U!UR�� �
U�Q_The 
Qformat
U argument is logged to the console; then either a panic (if in Kernel space) k.
        !           931: &UUR��@�
U
        !           932: �*or a core dump (if in user space) occurs.
        !           933: &:�m��UT`�
[URIOlibIOInit()
        !           934: &XUUR��`�
Usk2One-time only initialization of the libIO module.
        !           935: &oUUR��`�
U��&
        !           936: &�U   UR��`�
V#import <driverkit/libIO.h>
        !           937: &�UUR��`�
Uvoid 
VIOlibIOInit()
U;
        !           938: ��&�T�UR��`�
UUMDESCRIPTION
        !           939: 
U&�T�UR�� �
UobUIn the current implementation of libIO (which is not a shlib), this function must be �&�T�UR��@�
Uof1called once before using any functions in libIO.
        !           940: c
�F��UT`�
[.,IOIntToString()
        !           941: �+T�UR��`:
Use<Convert an integer to a string value via a regValues array.
        !           942: veBT�UR��`;
U��&
        !           943: oYT�UR��`<
Utr&
        !           944:  jT�UR��`=
VU5#import <driverkit/libIO.h>
        !           945: ���T�UR��`>
U<dGconst char *
VIOIntToString
U(int value, regValues *regValueArray)
        !           946: onsd_�U&``�RI$6�`�_
$6�^b| so(enURUR��`?
Uf DESCRIPTION
        !           947: e)UMUR��`A
U�=This function is the primary use of the following data type:
        !           948: �0������`�
I)
        !           949: typedef struct {
        !           950: k<������`�
Iitint rvValue;
        !           951: H������`�
IUconst char *rvName;
        !           952:        T������`�
I#i
} regValues;
        !           953: t`������`�
IUR&
        !           954: �rU9UR�� 9
UIYThis is the same thing as the Unix reg_values struct, and it�s used for the same thing - tU4UR��9
U lVto map integer values to strings. IOIntToString provides a method for mapping a given �U/UR��9
UctUint value to a string given an int an a pointer to an array of regValues�s. One very n�U*UR��9
UngRcommon use for this mechanism is to map IOReturn�s into error strings. IODevice�s �U%UR��9
U#iK-IOReturnToString: method performs this function. A subclass which defines ng�U UR��9
UVaGadditional IOReturn values should override this method and call [super ��UUR��9
UVIOReturnToString:] if it the specified value does not match one of the class-specific �UUR��@9
UIOIOReturn�s.
        !           955: ���UUR��`�
Uct&
        !           956:  &�b��UT`u
[ oXPR Functions
        !           957: &7UUR�� �
U��RXPR is a module which allows performance measurement and execution tracing with a &DUUR���
U*rSminimum of run-time intrusion. Using XPRs is kind of like using printfs to debug a UI&QT�UR���
U t\user-level program, except that making the XPR call which is equivalent to a printf is much to&^T�UR���
Us Mfaster (tens of microseconds on the 68040, we�ll see about the NRW) and each 9&kT�UR���
U aRprintf-equivalent is timestamped with microsecond accuracy. Typically a driver is &xT�UR���
UseVinstrumented with XPR functionality using a set of macros which are converted to NULL &�T�UR��@�
Utr-statements in release versions of the code. 
        !           958: w&�T�UR�� �
UU YThe basic mechanism of a printf-type operation in XPR is that a driver calls a function, &�T�UR���
UbxprAdd(), to add one entry to a circular buffer. Each entry consists of a list of stdargs, passed &�T�UR���
U�s[to xprAdd, as well as a timestamp and the current CPU number. Note that the first argument a m&�T�UR���
U pein a stdargs list is a string pointer; this pointer is stored in the circular buffer, not the string .&�T�UR���
Ud [itself. Later on, when the developer wishes to examine the XPR buffer contents, each entry ing&�T�UR���
Uh \is converted into a human readable string by sprintf�ing the arguments originally passed to 68&�T�UR��@�
Uut xprAdd(). (More on this below.)
        !           959: �T�UR�� �
UalZEach module has associated with it an array of mask bits which control the amount of data T�UR���
UR Ycollected at run time. For example, in a network driver, there might be one mask bit for m!T�UR���
Urs[�packet receive� code, one mask bit for �packet send� code, one packet for �configuration� PR .T�UR���
Ual]code, etc. Events associated with a given mask bit will only be collected if the mask bit is r;T�UR��@�
UstE1. These mask bits can be manipulated by the developer at run time. 
        !           960: tUT�UR�� �
Ut TThe developer can examine the printf-type strings by using an App called XPRViewer.  abT�UR���
UhiRAdditionally, in the kernel, one can examine the XPR strings from the NMI prompt. oT�UR���
UenQXPRViewer also allows manipulation of the mask bits and clearing the XPR buffer. �|T�UR���
Urt[XPRViewer is a separate task from the driver being tested (it can be on a separate host as ��da�bebb��$6�b�ait$6�`d| het URUR���
U��]well); it communicates with a server thread (in the driver or in the kernel, as the case may fUMUR���
U�Vbe) via Mach IPC; XPRViewer asks the server thread for entries, and the server thread !UHUR���
UURYsprintf�s the arguments in one entry in the circular XPR buffer and passes the resulting t.UCUR��@�
UT�Tstring back to XPRViewer, which displays the strings thus obtained in a ScrollView.
        !           961: 
        !           962: tHU>UR�� �
Ut TOne notable difference between the XPR module described here and the 2.0 kernel XPR  aUU9UR���
UhiWmodule is that there are multiple words of bit masks, allowing for more detailed event URbU4UR���
Uie[filtering. Also, in the XPRViewer App, bit masks are referred to by a human-readable name, UrtoU/UR���
UepZlike �Transmit� (for example). Other than at the time when various macros tailored to one |U*UR���
UbeWmodule are written, the developer never manipulates XPR mask bits as hex numbers, only `d�U%UR��@�
Ut as labels.
        !           963: ���v��UT`�
[mm
        !           964: xprInit()
        !           965: �UUR��`�
U(i0One-time only initialization of the XPR module.
        !           966: UM�UUR��`�
Ube&
        !           967: i&UUR��`�
Vwe#import <driverkit/uxpr.h>
        !           968: ent&U
UR��`�
Uervoid 
VxprInit
U();
        !           969: UR&>UUR��`�
UguDESCRIPTION
        !           970: nt&OUUR��`�
U XOThis must be called once before calling any other functions in the XPR module.
        !           971: r, &��T��UT`�
[ s       xprAdd()
        !           972:  &�T�UR��`�
Ull!Add one entry to the XPR buffer.
        !           973: o&�T�UR��`�
Uet&
        !           974: n&�T�UR��`�
Vsc#import <driverkit/uxpr.h>
        !           975:  XP&�T�UR��`�
U�Rvoid 
VxprAdd
U(char *str, int arg1, int arg2, int arg3, int arg4, int arg5);
        !           976: T�UR��`�
UURDESCRIPTION
        !           977: fiT�UR�� �
UthVThis is the exported function which is used to add events to the circular XPR buffer. "T�UR���
UitUHowever, drivers typically do not use this directly; instead, they should use macros �/T�UR���
UreRwhich call xprAdd() conditionally based on the current state of xprFlags. See the <T�UR��@�
Uas!section below under �XPR Macros�
        !           978: pVT�UR�� �
U��RThe last 5 arguments to this function are typed here as ints, but they are really cT�UR���
Uwe[untyped and could be any 32-bit quantity. They are stored in the XPR array as ints but are `�pT�UR���
Unt]eventually evaluated as arguments to sprint, so they could be ints, chars, shorts, or string d}T�UR��@�
UUT[pointers. See xpr_string(), below, for information on passing string pointers to xprAdd().
        !           979: Uetdc�<ddd�T�$6�d�c
U$6�bf|  i4,����UT`�
[URxprClear()
        !           980: DE&UNUR��`�
UURClear the circular XPR Buffer.
        !           981: d f=UIUR��`�
Use&
        !           982: oNUDUR��`�
V c#import <driverkit/uxpr.h>
        !           983: ��hU?UR��`�
U dvoid 
VxprClear
U();
        !           984:  �U:UR��`�
UteDESCRIPTION
        !           985: d �U5UR��`�
UUR?This one�s easy; it brings the XPR buffer to an �empty� state.
        !           986: entΪ���UT`�
[. xprSetBitmask()
        !           987: ���U,UR��`�
Ube/Set specified bitmask word to specified value.
        !           988:  la&U'UR��`�
Uth&
        !           989: f&U"UR��`�
Vhe#import <driverkit/uxpr.h>
        !           990: ly &.UUR��`�
Uwe9void 
VxprSetBitmask
U(int index, unsigned bitmask);
        !           991:  &NUUR��`�
Us DESCRIPTION
        !           992: �&_UUR�� �
Unt]This is typically used by individual User-level drivers at init time, if then. Subsequently, d&lUUR��@�
UUTWit is usually only used by the XPR server thread to change the current bitmask value. 
        !           993: ().&�U UR�� �
U_The 
Qindex
U argument is an index into the array xprMask[], which is an array of unsigned &�UUR��@�
U+ints, each of which contains 32 mask bits.
        !           994: DE&ȪU��UT`�
[URxprGetBitmask()
        !           995: ar&�T�UR��`�
UUI$Returns the specified bitmask word.
        !           996:  c&�T�UR��`�
Uit&
        !           997: pT�UR��`�
V��#import <driverkit/uxpr.h>
        !           998: U((T�UR��`�
U�+unsigned 
VxprGetBitmask
U(int index);
        !           999: s oHT�UR��`�
UgsDESCRIPTION
        !          1000: r YT�UR�� �
Ue.UThis is typically not used by drivers; it provides a procedural means of obtaining a  fT�UR���
UvaVspecified bitmask value. For performance reasons, the macros which are used to filter sT�UR���
UvoTand call xprAdd() typically read the index words directly (the xprMask[] array is a IO�T�UR��@�
U�    global).
        !          1001: ide�r-ff�ti$6�f�eUR$6�dh| he$er����UT`�
[ge
xpr_string()
        !          1002: t&UNUR��`�
UU   ,Return a malloc�d copy of specified string.
        !          1003: s =UIUR��`�
Uar&
        !          1004:  NUDUR��`�
Vs #import <driverkit/uxpr.h>
        !          1005: URhU?UR��`�
U, 6const char *
Vxpr_string
U(const char *instring);
        !          1006: �U:UR��`�
Uk(DESCRIPTION
        !          1007: ���U5UR�� �
UthXThis function is required when you want to use a pointer to a string whose existence is it�U0UR���
UUR[transitory as an argument. The reason for this is that the string itself won�t be accessed 
        !          1008: r �U+UR���
Ue.Uuntil the XPR buffer is examined, which could be a long time (minutes or more) after  �U&UR���
UvaYthe call to xprAdd(). By then, the string pointer passed to xprAdd() no longer points to ��U!UR��@�
Uana useful string.
        !          1009: i�UUR�� �
UexTOne big caution here! The string returned by this function will never be freed. Use �UUR��@�
Uwith discretion.
        !          1010: &(������`�
\Using XPR Macros
        !          1011: &CUUR�� �
U_Typically, drivers do not call xprAdd() directly. Instead, each driver (or kernel module) will urn&PU
        !          1012: UR���
Uf Yhave a set of macros which encapsulate the checking of the xprMask[] bits appropriate to >&]UUR��@�
U�0that module and conditionally calling xprAdd().
        !          1013: ns&wUUR��`�
U��FFor example, suppose driver �Stub� uses two mask bits in mask word 0:
        !          1014: &�������`�
Ise#import <driverkit/uxpr.h>
        !          1015: exi&�������`�
IUR&
        !          1016: �&�������`�
Iry:#defineSTUB_XPR_INDEX0// index into xprMask[]
        !          1017: &�������`5
IedA#defineSTUB_XPR_SEND0x00000001// mask bit for �send�
        !          1018: o&�������`�
I (D#defineSTUB_XPR_RECV0x00000002// mask bit for �receive�
        !          1019:  t&�������`�
Iin&
        !          1020:  &�T�UR��`�
U nOUseful macros to use in place of direct calls to xprAdd() would be as follows:
        !          1021: TOn&�������`�
I! <#define xpr_stub_send(x, a, b, c, d, e) {\
        !          1022: 
        !          1023: ������`�
I@if(xprMask[STUB_XPR_INDEX] & STUB_XPR_SEND) {\
        !          1024: UR������`�
Ica7xprAdd(x, (int)a, (int)b, (int)c, (int)d, (int)e);\
        !          1025:  dr"������`�
Idu}\
        !          1026: ��.������`�
Iet}
        !          1027: :������`�
Isu<#define xpr_stub_recv(x, a, b, c, d, e) {\
        !          1028: URF�~����`�
I m@if(xprMask[STUB_XPR_INDEX] & STUB_XPR_RECV) {\
        !          1029: FoR�{����`
I d7xprAdd(x, (int)a, (int)b, (int)c, (int)d, (int)e);\
        !          1030: ��^�x����`&
I<d}\
        !          1031: ��j�u����`
I
        !          1032: �}
        !          1033: v�r����`�
I#d&
        !          1034: ndg�exhh���$6�h�gEN$6�fj| 
        !          1035: o��URUR�� 
UinQThese macros would typically be conditional on an #ifdef UXPR (currently UXPR is nUMUR��
U�Sdefined to be 1 for DEBUG configurations); for release versions, the macros should TOn!UHUR��@
U! compile to �nothing�:
        !          1036: 9������`
I{)#define xpr_stub_send(x, a, b, c, d, e) 
        !          1037: iE������`
I_I(#define xpr_stub_recv(x, a, b, c, d, e)
        !          1038: URQ������`
Ica&
        !          1039: lU:UR��`
U(i(In the driver, the usage would just be 
        !          1040: ���������`
Iextern int foo;
        !          1041: ���������`
        !          1042: 
I}
        !          1043: &
        !          1044: ��������`       
I#d=xpr_stub_send(�Log this entry; foo = 0x%x\n�, foo, 2,3,4,5);
        !          1045: ~�U,UR�� �
Ui\The last 4 arguments are necessary to avoid compiler errors, since xpr_stub_send() requires (x�U'UR���
U(iW6 arguments. Some programmers will surely find ways around this hassle; the above form I
        !          1046: ��U"UR��@�
U�Xmerely keeps one on one�s toes to ensure that one knows what arguments are going where.
        !          1047: &������`�
\!Standard XPR #defines and Macros
        !          1048: o& UUR�� �
U��WThe file <driverkit/DeviceUxpr.h> contains common bit mask and macro definitions which s n&-UUR���
U�Zare used by the libDev device classes. Other drivers should not use these same bit masks. &:UUR��@�
UcoFCommon bit masks for kernel drivers are in <driverkit/KernDevUxpr.h> 
        !          1049: di�#djj� a$6�j�ica$6�hl| he" w
        !          1050: ��
        !          1051: ��UUh�
[��-&i
ZThe Thread Based Model of Device I/O
        !          1052: �B����UT`
[�� Overview
        !          1053: d]UMUR�� 
UogZThe traditional Unix device driver design involved a conceptual �top half�, which is code jUHUR��
Uco`called from higher layers in the kernel to initiate an I/O, and a �bottom half�, which consists s wUCUR��
Uay\of various interrupt handlers and I/O complete logic. The simple model of an I/O using this o �U>UR��@
Uowdesign is:
        !          1054: nts�U9UR�� 
U_Higher level Kernel code calls the driver�s strategy() or write() (or ...) routine to start an /De�U4UR��@
UnsI/O.
        !          1055:  �U/UR�� 

U dXThe strategy() routine enqueues the I/O on an I/O queue which is private to the driver, ve�U*UR��@

UthSperhaps after massaging the incoming data structure into a driver-specific format.
        !          1056: <dr�U%UR��`
Ur.\If the bottom half of the driver is idle, call a start() routine to get the hardware going.
        !          1057: &U UR�� 
URThe bottom takes over from here. When an interrupt occurs, the driver�s interrupt &UUR��
U
        !          1058: �Shandler runs and either decides that the hardware needs some more attention before ver& UUR��
U cTcompleting the I/O (in which case a state machine is advanced and the driver awaits  t&-UUR��
UatXanother interrupt), or that the I/O is complete (in which case higher level code in the  h&:UUR��@
Ump"kernel is notified of this fact).
        !          1059: &TUUR�� 
UU>\Things actually get much more complicated than this. For one thing, there tends to be a lot r�&aUUR��
UitZof code that sometimes runs at interrupt level and sometimes runs at ipl0. One example of &nT�UR��
Unq`this kind of code is the routine that starts up an I/O. In the above example, this code runs at r &{T�UR��
Umi]ipl0, but if at I/O complete time there is more work to be done, the interrupt handler calls  &�T�UR��@
U, the startup routine as well. 
        !          1060: &�T�UR�� 
U]Portions of device driver code which run at interrupt level can get out of control resulting n&�T�UR��
U��Yin cases where some interrupts are disabled for hundreds of microseconds (or even more), e&�T�UR��
UYseriously hampering system throughput and crippling the ability of the system to respond t&�T�UR��@
Uat6to real time events like the arrival of serial data. 
        !          1061: &�T�UR�� 
UveWAnother problem with running some subset of a driver�s code at interrupt level is that UU>&�T�UR��
Uge]performing locking of shared data structures (even if they are only shared between the files t&�T�UR��
Uet\comprising one device driver) is difficult on a multiprocessor system. To access a critical th
        !          1062: T�UR��
U t\data structure on a multiprocessor system, when the data can be accessed at interrupt level miT�UR��
UI/\by all CPUs, non-interrupt code must first disable interrupts on both CPUs and then acquire , $T�UR��@
Uin    a lock. 
        !          1063: 
        !          1064: >T�UR�� 
UYNRW device drivers have avoided all of these problems by disposing of the Unix model and iKT�UR��@
UIchoosing instead a thread-based paradigm. Basically, the model is this: 
        !          1065: neT�UR��`
U e@Drivers are notified of hardware interrupts via Mach messages. 
        !          1066: ipdk� rll�$6�l�k a$6�jn| ve!heURUR�� 
UniWThere is one thread which is responsible for any given hardware device. This thread is forUMUR��@
Uarcalled an I/O thread.
        !          1067: .UHUR�� 
UshUAt any given time, a driver�s I/O thread is either executing (i.e., dealing with the t;UCUR��@
UorNhardware) or waiting for one of two things - new work to do, or an interrupt.
        !          1068: UU>UR�� 
UheYThis model is intended to be used for drivers both in the Kernel and in User space. This rbU9UR��@
UstQmodel has been found to simplify driver development and to minimize debug time. 
        !          1069: 
        !          1070: |U4UR��`
U?The above three bullet items each merit a detailed discussion.
        !          1071: ing�����UT`
[ aInterrupt Notification
        !          1072: Ich�U+UR�� 
Uhr[As far as the low-level kernel code is concerned, handling device interrupts is easy. When d o�U&UR��
Upt\an interrupt occurs, the kernel masks off further occurrences of that particular interrupt, �U!UR��
U\sends a message to a port, and returns from the interrupt. The port to which the �interrupt ea�UUR��
UibZmessage� is sent belongs to a device driver, which at some time previously has registered &UUR��
Uathis port to be associated with this particular interrupt. Each interrupt bit is associated with R&
UUR��
Uwa_either 0 or 1 interrupt ports. (See the section of this document entitled �Kernel Level Driver s m&U
UR��
Uo ZSupport� for details on the interrupt port registration mechanism.) The interrupt message &'UUR��
UsiYcontains no information other than a msg_id in its message header, which identifies this e&4UUR��
Uh ]message as an interrupt message. It is up to the driver to receive this message, examine the &AT�UR��
Ue [hardware to determine the cause of the interrupt, perform whatever action is necessary for &NT�UR��
U oZcontinuing the I/O in progress, and finally to notify the kernel that it should re-enable &[T�UR��
Ume[interrupt notification for the device in question. Only when the kernel is so notified can ��&hT�UR��@
U i1another interrupt message be sent to the driver.
        !          1073: m&��@��UT`
[egOne Device, One Thread
        !          1074: U&�T�UR�� 
Uas[A device driver is responsible for maintaining and dealing with three kinds of resources - &�T�UR��
U1 \hardware, private data, and client I/O requests. In a multiprocessor system, or in a system ��&�T�UR��
U f]in which device driver code contains actual interrupt handlers, a great deal of care must be &�T�UR��
Uinbtaken to protect access to all three of these resources; locks and spl()�s are required in almost &�T�UR��
Uup[every routine. Looking at the current m68k drivers, it is apparent that even with the most [ha&�T�UR��
Ue Ywell-thought out design, the need for spl()�s and locks has caused a lot of problems and oT�UR��
U/OXextra crufty code. This problem is most apparent in code which manipulates the hardware meT�UR��@
Uca
        !          1075: directly.
        !          1076: -T�UR��`
Un.,There is a simple solution to this problem:
        !          1077: T�GT�UR��  
UanVGiven any hardware resource, one and only one thread can deal with that resource at a TT�UR��@ 
U��>time. The resource is never accessed in an interrupt handler.
        !          1078: dm� -nn�1 $6�n�mnt$6�lp|  o' sURUR�� !
U��YFor example, take the SCSI controller chip. If there is exactly one thread in the system aUMUR��!
UUR^which can access that resource, there is no need for locking or for spl()�s around code which !UHUR��@!
UT�accesses this hardware. 
        !          1079: t;UCUR�� "
Ue ^Another way of looking at this is that for a given piece of hardware, there is only one thing HU>UR��"
U n^which can be happening at a time. At point A, a driver might be setting up a chip to start an UU9UR��"
Uis]I/O. At point B, the driver might be waiting for an interrupt from the chip. At point C, the RbU4UR��"
Ue ^driver might be responding to an interrupt and interrogating registers to see what caused the oU/UR��"
U ccinterrupt. A driver is never setting up a chip to start an I/O at the same time it�s interrogating rru|U*UR��"
U]registers to see what caused an interrupt. All these operations are single threaded. In Unix �U%UR��"
UYdrivers, this single threading is performed by a combination of locking, spl()�s, and an f�U UR��"
Uon]interrupt-driven state machine. In the NRW, this single threading is done by, well, a single f�UUR��@"
Usp0thread. Let�s call this thread an �I/O thread�.
        !          1080: ss�UUR�� #
U
        !          1081: t[Another reason for this model is the desire to have drivers run in user space. There is no her�UUR��#
Ug Xpractical way for User-level drivers to actually run interrupt handlers with interrupts in�UUR��#
UrtVdisabled. The fundamental quanta of program control in User space is the thread. Some �UUR��#
UpoUdrivers in exceptional cases may choose to have multiple threads access one piece of o�UUR��#
Uo [hardware; the �one device, one thread� model is not an absolute. It�s merely a design goal tar�T�UR��@#
UmeFwhich has proved to be a viable basis for writing NRW device drivers.
        !          1082: &3�N��UT`
[t.Simple Thread Model
        !          1083: ar&NT�UR�� $
U I\Let�s look at a simple piece of hardware, the Floppy controller chip. Floppy I/O is totally lo&[T�UR��$
Ud `single threaded - you start up an I/O, wait for an interrupt, diddle some registers, and you�re e &hT�UR��$
U f\done. A single thread which �owns� this controller chip is doing one of three things - it�s An&uT�UR��$
Uhibidle and waiting for work to do, it�s executing (i.e., twiddling bits in the controller chip), or &�T�UR��$
Uev]it�s waiting for an interrupt. That�s all it ever does. At the highest level, the Floppy I/O  &�T�UR��@$
Uanthread looks like this:
        !          1084: se&�������`%
IeafloppyThread()
        !          1085: ��&������`&
Iin{
        !          1086: &��|����`'
I c#initialize local data structures;
        !          1087:  on&��y����`)
IURinitialize hardware;
        !          1088: &��v����`*
Inewhile(1) {
        !          1089:  i&��s����`+
I I)wait for an I/O request from a client;
        !          1090: #&��p����`-
Iov/set up the controller chip to start the I/O;
        !          1091: ive&��m����`.
Iwait for interrupt;
        !          1092: �j����`/
I$6diddle with controller registers to finish the I/O;
        !          1093: �g����`0
I. !notify client of I/O complete;
        !          1094: ��d����`,
Ihr}
        !          1095:  - +�a����`(
IO,}
        !          1096: FT�UR�� 1
U, bNot all devices are this simple, but this illustrates how a single thread is sufficient to do all ST�UR��@1
Uoi1the manipulation of a single hardware resource. 
        !          1097: ido� ipp�wi$6�p�o),$6�nr|  a(rr������`W
\ e:Communication between Exported Methods and the I/O Thread
        !          1098: "UOUR�� 2
UooYThe one tricky part of this model is the communication between a driver class�s exported �/UJUR��2
UizVmethods and the I/O thread. In some cases, an exported method needs to do synchronous <UEUR��2
U i[communication with the I/O thread - that is, the exported method wants to send some quanta p tIU@UR��2
U t`of work to the I/O thread and wait (sleep) until that work is done. In other cases, an exported h VU;UR��2
Urs\method does asynchronous I/O - it just wants to send a quanta of work to the I/O thread and hrcU6UR��@2
U��be done with it.
        !          1099: R}U1UR�� X
UalQBoth types of I/O - synchronous and asynchronous - can be performed via Mach IPC o�U,UR��X
U��Ybetween the exported methods and the I/O thread. This technique is 
Vnot
U generally �U'UR��X
UTrecommended, but it�s sometimes useful. A Mach IPC interface is generally done with  a�U"UR��X
U��VMIG, though some programmer prefers hand-coded messages and explicit msg_rpc() calls. �UUR��@X
Uar3This technique is adequately documented elsewhere.
        !          1100:  cl�UUR�� Y
UUJVOne reason that this technique is generally not recommended for communication with an �UUR��Y
UUEVI/O thread is performance. A msg_rpc() between threads in one task (which is the case �UUR��Y
UtaXwhen a class�s exported method wishes to communicate with that class�s I/O thread) is a ne�U UR��Y
Uan[pretty heavyweight operation. A more efficient way to do this is with condition locks. The ta �UUR��Y
U tVclass NXConditionLock is documented elsewhere; this is the typical mechanism by which &T�UR��Y
UanXexported methods send I/O requests to an I/O thread and by which exported methods sleep  m&T�UR��Y
U tYuntil an I/O request is complete. (Note: I know that User level implementations of sleep  &&T�UR��Y
UA Plocks and condition locks currently use Mach RPC as their underlying mechanism.  p&3T�UR��Y
Uha[Hopefully, this will not always be the case. Kernel level implementations of both of these ate&@T�UR��@Y
Uwh(use lower-level scheduling primitives.)
        !          1101: ha&ZT�UR�� E
Us WAnother reason this technique is to be avoided is that using Mach messages to transfer erf&gT�UR��E
U()\information between threads in a single task is kind of messy; most of the information in a me&tT�UR��E
UmuYMach message exists to allow marshalling of various data types and to facilitate sending i&�T�UR��E
Unt]complex data over a network interface. Neither of these operations of required for intratask d&�T�UR��@E
Ue;communication.
        !          1102: cal&�T�UR�� Z
Uh ZThe general technique for passing I/O information from a driver�s exported methods to its &�T�UR��@Z
U mI/O thread is as follows:
        !          1103: &�T�UR�� [
UcoPDefine a struct which will serve as a �command buffer�, the fundamental unit of A &�T�UR��[
UioNcommunication between exported methods and the I/O thread. The command buffer &�T�UR��[
Uhi\(let�s call it a cmdBuf_t) is different for each driver; it contains all of the information Y&�T�UR��[
UveUneeded by the I/O thread to perform a single I/O. For example, a cmdBuf_t for a disk eT�UR��[
UsiXdriver might contain a disk address, a VM address, a byte count, and a read/write flag. glT�UR��[
UmeRThe cmdBuf_t also contains fields by which the I/O thread can indicate completion T�UR��@[
UvaVstatus - for example, a device-specific status field and a �bytes transferred� field.
        !          1104: 7T�UR�� ^
UeiNThe cmdBuf_t also contains an NXConditionLock. This lock will be the means by DT�UR��^
UURVwhich an exported method sleeps until an I/O is complete. We�ll call this cmdBufLock. QT�UR��^
UT�DcmdBufLock�s condition variable will have two states - COMPLETE and ne^T�UR��@^
UllNOT_COMPLETE.
        !          1105: dq� orr�io$6�r�qet$6�pt| r 0URURUR�� \
U�sTDeclare a queue as an instance variable on which cmdBuf_t�s are enqueue by exported YUMUR��\
UveUmethods and dequeued by the I/O thread. This queue will be referred to as ioQueue in e!UHUR��\
UsiVthis discussion. (The implementation of the queue - singly linked list, Mach queue_t, .UCUR��@\
U[.etc., isn�t important; it�s device-specific.)
        !          1106: HU>UR�� ]
Un TDeclare an NXConditionLock as an instance variable; this protects the I/O queue and usUU9UR��]
Us ]also provides a way for the I/O thread to sleep until it has work to do. We�ll refer to this obU4UR��]
UnsHas ioQueueLock. ioQueueLock�s condition variable will have two states - cooU/UR��@]
U t!QUEUE_EMPTY and QUEUE_NOT_EMPTY.
        !          1107: ��U*UR��`_
UdiJAn exported method wishing to perform synchronous I/O does the following:
        !          1108: �������``
I+- (IOReturn)someMethod : (int)someArgument
        !          1109: �������`a
I{
        !          1110: �������`f
IcmdBuf_t cmdBuf;
        !          1111: �������`g
Ir &
        !          1112: �������`d
I\0fill in cmdBuf fields appropriate to this I/O;
        !          1113: hi�������`h
Ien4Initialize cmdBufLock to condition �NOT_COMPLETE�;
        !          1114: de�������`i
Ith&
        !          1115: d�������`j
Ibe/*
        !          1116: re&&������`k
I eC * Enqueue this cmdBuf on ioQueue and let I/O thread know that it
        !          1117: ue &
������`m
Ist * has work to do.
        !          1118: UR&������`l
I,  */
        !          1119: m&%������`b
Ice[ioQueueLock lock];
        !          1120: �&1������`e
Ianenqueue cmdBuf on ioQueue;
        !          1121: e &=������`n
Ite4[ioQueueLock unlockWithCondition:QUEUE_NOT_EMPTY];
        !          1122: vi&I������`o
II/&
        !          1123: h&U������`p
Il /*
        !          1124:  w&a������`q
Ief?  * Now wait for I/O thread to process the cmdBuf and signal 
        !          1125: ond&m������`r
Il  * completion.
        !          1126: co&y������`s
I t */
        !          1127: _&�������`t
IT_)[cmdBuf.cmdBufLock lockUntil:COMPLETE];
        !          1128: e&�������`u
Irf[cmdBuf.cmdBufLock unlock];
        !          1129: l&�������`�
I��&
        !          1130: `&�������`v
Iso/*
        !          1131: od&�������`w
Int  * I/O is complete. 
        !          1132: {
        !          1133: &�������`x
I */
        !          1134: u&�������`y
I��"Free necessary data from cmdBuf;
        !          1135: &�������`z
IfiReturn I/O result;
        !          1136: is&�������`c
I��}
        !          1137: &��}����`{
Icm&
        !          1138: fT�UR��`|
U�NXThe I/O thread calls the following while awaiting work to do from the exported methods:
        !          1139:  $�u����`}
IBu&
        !          1140: n0�r����`~
I/O- (cmdBuf_t *)waitForWork
        !          1141: <�o����`
I {
        !          1142: H�l����`�
I��cmdBuf_t *cmdBuf;
        !          1143: /
        !          1144: mT�i����`�
Ice&
        !          1145: [`�f����`�
I
        !          1146: �*[ioQueueLock lockUntil:QUEUE_NOT_EMPTY];
        !          1147: l�c����`�
I��*dequeue head of ioQueue, save in cmdBuf;
        !          1148: x�`����`.
Iviif(ioQueue empty)
        !          1149: &
        !          1150: h��]����`�
Il ([ioQueueLock unlockWith:QUEUE_EMPTY];
        !          1151: t ds�uftt���$6�t�s��$6�rv| T_(dB������`/
IUnelse
        !          1152: P������`0
I��+[ioQueueLock unlockWith:QUEUE_NOT_EMPTY];
        !          1153: ��������`�
I��return cmdBuf;
        !          1154: /)������`�
Iw}
        !          1155: 5������`5
Ile&
        !          1156:  PUCUR�� 6
UxYAfter performing the I/O, the I/O thread does the following to notify the client (who is R]U>UR��@6
UisBsleeping in the exported method which generated the I/O request):
        !          1157: u������`7
Ial&
        !          1158: t�������`8
I a*- (void)doIoComplete : (cmdBuf_t *)cmdBuf
        !          1159: �������`9
I}{
        !          1160: �������`:
I~[cmdBuf->cmdBufLock lock];
        !          1161: k
        !          1162: �������`<
I +[cmdBuf->cmdBufLock unlockWith:COMPLETE];
        !          1163: /
        !          1164: m�������`;
Ice}
        !          1165: �������`4
\
        !          1166: �1Other types of communication with the I/O Thread
        !          1167: �&&U$UR�� 3
UueRAsynchronous I/O is a subset of the above code example. For asynchronous I/O, the &UUR��3
ULexported method does not have to do a lockUntil: on cmdBuf.cmdBufLock after &UUR��3
U��Tenqueueing the cmdBuf on ioQueue; the method returns immediately. Likewise, the I/O dB&(UUR��@3
UUn/thread need not call the doIoComplete: method.
        !          1168: kWi&BUUR�� =
U];YSome drivers require their I/O threads to be able to service incoming I/O requests while  &OUUR��=
UxYwaiting for interrupt messages. The SCSIController class is an example of this. The SCSI R&\UUR��=
UisWbus is capable of performing overlapped I/Os, in which one I/O can be started up while &
        !          1169: t&iU&UR��=
U a^another I/O is in progress and is disconnected from the bus. In this case, the SCSIController &vT�UR��=
Uk]]I/O thread receives both its I/O requests as well as its interrupt messages on the same port 
        !          1170: &�T�UR��=
U
        !          1171: �Yset. The port set consists of an interrupt port and a command port. Messages sent to the i&�T�UR��=
UabVcommand port are �Mach message wrappers� around a cmdBuf_t-type structure. (Actually, &�T�UR��=
UckWthe messages merely contains a pointer to a cmdBuf_t; this of course couldn�t work for e; &�T�UR��=
U iSmessages which are passed between tasks, but the SCSIController�s exported methods mpl&�T�UR��=
UUValways execute in the same memory address space as its I/O thread.) Sometimes the I/O &�T�UR��=
U  Vthread needs to only wait for an interrupt, without wanting to deal with incoming I/O &�T�UR��=
USC_requests; in this situation, the I/O thread removes the command port from its port set so that tar&�T�UR��=
UU&[it only will respond to interrupts. When it is able to deal with I/O requests, it adds the the&�T�UR��@=
UT�%command port back into its port set.
        !          1172: oT�UR�� >
Us XSometimes, for performance (or other) reasons, a driver might have its exported methods t T�UR��>
UerZperform some I/O directly without going through the I/O thread. The Ethernet driver is an T�UR��>
UerWexample of this. The netOutput: method, which is called when a client wishes to send a  co,T�UR��>
Uo Zpacket out to the net, usually performs no I/O - it just adds a DMA frame to the device�s 9T�UR��>
U bXDMA queue. The exported method does this directly without waking up the I/O thread. The meFT�UR��>
UacXEthernet I/O thread basically just services interrupts and dispatches incoming packets. r ST�UR��>
Uou]There is a lock implemented in the driver to allow this type of behavior. This lock protects t`T�UR��@>
Uco]access to the hardware in the case where the netOutput has to start up an idle DMA channel. 
        !          1173: sdu� rvv�he$6�v�u b$6�tx| s      ti������`?
\;Summary
        !          1174: ) "UOUR�� @
UmiXThe above model is just provided as a guide. As evidenced by the previous section, some in/UJUR��@
UthYdriver have their own peculiar I/O thread communication requirements and many variations d<UEUR��@
Uwh]on this standard model will exist. However, it�s clear that each driver which has to respond oIU@UR��@
Us Zto interrupts has to have at least one thread (which does msg_receive()�s on an interrupt VU;UR��@
Ukidport); the premise being made here is that these drivers should have 
Vexactly
U one I/O thread tscU6UR��@@
UcoWwhich services interrupts and does as much of the low-level bit twiddling as possible.
        !          1175: thi}U1UR�� A
U. XSee the section of this document entitled �Code Examples� for more illustrations of the Ou�U,UR��@A
Uupconcepts presented above.
        !          1176: dw�xx�$6�x�w$6�vz| !��
        !          1177: ��
        !          1178: ��UUh&
Z��$&j&1Kernel-Level Driver Support
        !          1179: e 'UQUR�� Y
Uid=This section describes an interface which was designed to be J4ULUR��Y
Udr[architecture-independent as much as possible. Due to the nature of the functions described URAUGUR��Y
Uhi_here, there are a number of limitations and qualifications referring to architecture type. The ��NUBUR��@Y
UruSarchitectures are referred to as �m68k� (current 680x0 products) and �m88k� (NRW).
        !          1180: UR�����UT`L
[);
Device Ports
        !          1181: i�U9UR�� Z
UatYRights to access a device's registers, to program its DMA channel, and receive interrupt v�U4UR��Z
Ud ^notification are conveyed by a task holding send rights to a per-device port referred to here �U/UR��Z
U efas the 
QdevicePort
U. The kernel responds to requests sent on the devicePort in order to provide �U*UR��Z
U�_these services to the requesting task. devicePort's are created early in system initialization �U%UR��Z
U^and passed out to the appropriate device drivers by a process that is described later, in the �U UR��Z
Un Zsection entitled �Autoconfiguration�. Operations are performed upon device ports by a via �UUR��@Z
U tRPCs to a kernel server.
        !          1182: d&!�l��UT`[
[URRegister Mapping
        !          1183:  &<UUR�� \
U o[This interface provides various mechanisms for device drivers to map the physical register Sar&IU
UR��\
Ufe[space associated with their devices into their local address space. Which mechanism(s) can Por&VUUR��\
UZZbe used by a particular device driver are determined by the machine architecture, whether &cUUR��@\
UZ_the device is a native device or a NextBus device, and the Slot ID in which the device lives. 
        !          1184: re &}T�UR�� ]
U e_For the purposes of the following discussion, an 
VNRW DMA Device
U is defined as a device rov&�T�UR��]
UZ[in an m88k machine which resides in a slot with whose NextBus slot Id bits 9 through 7 are iza&�T�UR��@]
U��`'111'. A 
Vnative m68k device
U is a device which is an integral part of an m68k-based CPU.
        !          1185: n &�T�UR�� ^
UZ[There are three kinds of device register space which can be mapped in to a device driver's ia &�T�UR��@^
U tlocal address space:
        !          1186: e&�T�UR�� _
V[\Register Space
U consists of one page (the size of which is machine dependent but can for ev&�T�UR��_
U tYnow be assumed to be 8k bytes) consisting of device-specific registers. For NRW devices, r&�T�UR��_
Uce]the format of a device page is defined in the NRW system specification, section 5.2.8.2. For e&�T�UR��_
UinZm68k devices, a device page is the physical memory region comprising all of the registers T�UR��@_
UID\in one native device; the start of the register space may not be page-aligned in this case.
        !          1187: si&T�UR��``
] Dm88k devices:
        !          1188: @T�UR�� a
UovTA driver can map in a register page if and only if it is associated with an NRW DMA otMT�UR��@a
U 7      Device. 
        !          1189: �gT�UR��`b
]'1m68k devices:
        !          1190: �T�UR��`c
U�_A driver can map in a register page if and only if it is associated with a native device.
N 
        !          1191:  kidy� czz�ev$6�z�y t$6�x|| [stURUR��`d
NstP
VSlot Space 
Uconsists of up to 16 MB of memory, starting at 0xfs000000. 
        !          1192: _!UMUR��`e
]edm88k devices:
        !          1193: ;UHUR�� f
UicKAn NRW DMA device driver can map in the first 0xf00000 (15 M) bytes of its  deHUCUR��f
UedTassociated slot space, or a portion thereof. A non-NRW DMA device driver can map in icUU>UR��@f
Uis7all 16 MB of its slot space, or a portion thereof
N.
        !          1194: rs oU9UR��`g
]IDm68k devices:
        !          1195: �U4UR�� h
UofUOnly drivers associated with non-native devices can map in slot space; native device d�U/UR��@h
U��1drivers have no slot space associated with them.
        !          1196: d�U*UR��`i
VocBBoard space 
Uconsists of up to 256 MB, starting at 0xs000000. 
        !          1197: �U%UR��`j
]icm88k devices:
        !          1198: �U UR�� k
U cXDrivers associated with devices in slots 13 and 14 are allowed to map in all or part of �UUR��@k
UAtheir board space. Other drivers can not map in any board space.
        !          1199: &UUR��`l
]m68k devices:
        !          1200: &%UUR��`m
UstHOnly drivers associated with non-native devices can map in board space.
        !          1201: y,&Z�b��UT`
[00Initialization RPCs
        !          1202: e&��^��UT`p
[:
        !          1203: IOAttachInterrupt()
        !          1204: An&�UUR��`q
Uiv Request interrupt notification.
        !          1205: 15&�T�UR��`r
Ude&
        !          1206: C&�T�UR��`s
Vas"#import <driverkit/user_driver.h>
        !          1207: &�T�UR��`t
UMA&IODeviceReturn 
VIOAttachInterrupt(
        !          1208: &�T�UR��`u
UB $IODevicePort 
QdevicePort
U,
        !          1209: f
        !          1210: T�UR��`v
U��port_t 
Qintr_port
U);
        !          1211: T�UR��`w
U d&
        !          1212: e7T�UR��`x
U n
DESCRIPTION
        !          1213: eHT�UR�� y
VspUIOAttachInterrupt
U() requests that interrupt notification messages for the device eUT�UR��@y
UiIrepresented by 
QdevicePort
U be sent to the port 
Qintr_port
U.
        !          1214: %oT�UR�� z
Um8YOnly a single port may be attached for device interrupts at any point in time. (A policy l|T�UR��@z
U o-decision, more than functional requirement.)
        !          1215: pd{�an||�UR$6�|�{UR$6�z~|  nivURUR��`{
UinPIn NRW, this request also binds a device interrupt with a global interrupt bit.
        !          1216: IO!UMUR��`|
QAnFdevicePort
U is the port representing the device access capability.
        !          1217: ;UHUR��`}
Q��Qintr_port
U is the port to which interrupt notification messages will be sent.
        !          1218: Vp����UT`~
[(
        !          1219: IODetachInterrupt()
        !          1220: �U?UR��`
Ude Disable interrupt notification.
        !          1221: ���U:UR��`�
Utr&
        !          1222: r�U5UR��`�
V��"#import <driverkit/user_driver.h>
        !          1223: �U0UR��`�
UUR*IODeviceReturn 
VIODetachInterrupt
U(
        !          1224: �U+UR��`�
Uno#IODevicePort 
QdevicePort
U,
        !          1225: UT��U&UR��`�
Ureport_t i
Qntr_port
U);
        !          1226:  &
        !          1227: U!UR��`�
Ut 
DESCRIPTION
        !          1228: U&$UUR�� �
VzSIODetachInterrupt
U disassociates interrupt notification messages for the device (A &1UUR��@�
U��Hrepresented by 
QdevicePort
U from being sent to 
Qintr_port
U.
        !          1229: �&f�h��UT`�
[IOAttachChannel()
        !          1230: &�UUR��`�
U�,Attach a DMA channel to a specified device.
        !          1231: ~&�U  UR��`�
Uiv&
        !          1232: R&�UUR��`�
VIn"#import <driverkit/user_driver.h>
        !          1233: &�T�UR��`�
Ua (IODeviceReturn 
VIOAttachChannel
U(
        !          1234: An&�T�UR��`�
Us #IODevicePort 
QdevicePort
U,
        !          1235: ss &�T�UR��`�
UURint 
QchannelNumber
U,
        !          1236: t&�T�UR��`�
UntBOOL 
Qstream_mode
U,
        !          1237: il&�T�UR��`�
U��int 
Qbuffer_size
U);
        !          1238: t(T�UR��`�
U
DESCRIPTION
        !          1239: n+T�UR�� �
VonIIOAttachChannel
U associates a system-wide global DMA channel with the r8T�UR��@�
U��edevice-specific local channel 
QchannelNumber
U of the device represented by 
QdevicePort
U.
        !          1240: RT�UR�� �
U��UA 
VIOAttachChannel
U must be performed for each physical DMA channel to be used �_T�UR��@�
UInwith the device. 
        !          1241: yT�UR��`�
QtiFdevicePort
U is the port representing the device access capability.
        !          1242: d}�t ~~��$6�~�}ne$6�|�| nna URUR�� �
Q~WchannelNumber
U is the device-specific local DMA channel number that should be bound ��UMUR��@�
URewith a global DMA channel.
        !          1243: 
        !          1244: An.UHUR�� �
Qs Tstream_mode
U specifies whether or not the device-specific hardware is capable of 
U;UCUR���
U�Rgenerating an End Of Record signal on input. See the description for IOEnqueueDma HU>UR��@�
U�1for more information on streaming mode channels.
        !          1245: hbU9UR�� �
QesZbuffer_size
U is the device-specific DMA buffer size. The kernel needs this information oU4UR���
UbeQwhen performing DMA dequeue operations; it is also used in verifying correct DMA |U/UR��@�
U alignment.
        !          1246: rme�����UT`�
[l IODetachChannel()
        !          1247: �U&UR��`�
U�(Dissociate a DMA channel from a device.
        !          1248: ti�U!UR��`�
Us &
        !          1249:  �UUR��`�
Vth"#import <driverkit/user_driver.h>
        !          1250: &UUR��`�
U(IODeviceReturn 
VIODetachChannel
U(
        !          1251: &UUR��`�
U#IODevicePort 
QdevicePort
U,
        !          1252: |&+U
UR��`�
UURint 
QchannelNumber
U);
        !          1253: &KUUR��`�
Usp
DESCRIPTION
        !          1254: A&\UUR�� �
VatWIODetachChannel
U disassociates the local DMA channel 
QchannelNumber
U from the Qs &iT�UR��@�
Usp*device represented by 
QdevicePort
U.
        !          1255: &��O��UT`�
[ oIOMapDevicePage()
        !          1256: &�T�UR��`�
Un 1Map a device page into a driver�s address space.
        !          1257: f&�T�UR��`�
UU>&
        !          1258: R&�T�UR��`�
Vmo"#import <driverkit/user_driver.h>
        !          1259: &�T�UR��`�
U��(IODeviceReturn 
VIOMapDevicePage
U(
        !          1260: ecT�UR��`�
Uze#IODevicePort 
QdevicePort
U,
        !          1261: oU4T�UR��`�
Uwh!vm_task_t 
Qtarget_task
U,
        !          1262: s%T�UR��`�
Uin1vm_offset_t *
Qaddr
U,/* in/out */
        !          1263: m2T�UR��`�
UUTBOOL 
Qanywhere
U);
        !          1264: RT�UR��`�
U�DESCRIPTION
        !          1265:  DcT�UR�� �
UdeLIOMapDevicePage maps the device register page of the device associated with drpT�UR���
U��XdevicePort into the target task at addr. This RPC is invalid for m88k devices which are 
Q}T�UR��@�
U5not NRW DMA devices and for non-native m68k devices.
        !          1266: d�U���ta$6���ca$6�~�| heT�URUR��`�
Qde=devicePort
U is the kernel provided handle for the device.
        !          1267: O!UMUR��`�
QT�Ztarget_task
U represents the address space into which the device page should be mapped.
        !          1268: ;UHUR��`�
QmoWaddr
U is the address in 
Qtarget_task
U where the device page should be mapped.
        !          1269: ageUUCUR�� �
Q��Wanywhere
U is a boolean; if YES, indicates the kernel may pick any unused address to getbU>UR��@�
UURmap the device page.
        !          1270: e�����UT`�
[IOUnmapDevicePage()
        !          1271: T��U5UR��`�
U4Remove a device page from a driver�s address space.
        !          1272: IO�U0UR��`�
U�&
        !          1273: e�U+UR��`�
Vma"#import <driverkit/user_driver.h>
        !          1274: �U&UR��`�
Uit*IODeviceReturn 
VIOUnmapDevicePage
U(
        !          1275: &U!UR��`�
Udd#IODevicePort 
QdevicePort
U,
        !          1276: es &UUR��`�
UUR!vm_task_t 
Qtarget_task
U,
        !          1277: n&UUR��`�
U68vm_offset_t 
Qaddr
U);
        !          1278: �&>UUR��`�
UDESCRIPTION
        !          1279: &OU
UR�� �
VTIOUnmapDevicePage
U unmaps the device register page of the device associated with �&\UUR���
QUhdevicePort
U. 
Qtarget_task
U and 
Qaddr
U must match similar parameters passed to a previous ss&iUUR��@�
Uthcall to IOMapDevicePage().
        !          1280: d.
        !          1281: &��T��UT`�
[moIOMapSlot()
        !          1282: th&�T�UR��`�
Uar.Map slot space into a driver�s address space.
        !          1283: &�T�UR��`�
U��&
        !          1284: �&�T�UR��`�
V i"#import <driverkit/user_driver.h>
        !          1285: &�T�UR��`�
U u"IODeviceReturn 
VIOMapSlot
U(
        !          1286: T�UR��`�
Uce#IODevicePort 
QdevicePort
U,
        !          1287: DevT�UR��`�
UUR!vm_task_t 
Qtarget_task
U,
        !          1288: f%T�UR��`�
Urevm_offset_t 
Qoffset
U,
        !          1289: 2T�UR��`�
U�vm_size_t 
Qlen
U,
        !          1290: e?T�UR��`�
UUR1vm_offset_t *
Qaddr
U,/* in/out */
        !          1291: 
LT�UR��`�
U�BOOL 
Qanywhere
U);
        !          1292: fT�UR��`�
UU&
        !          1293: Rd��et�����$6����U$6���| U
��URUR�� �
Vev`IOMapSlot
U maps the slot space of the NeXTbus device associated with 
QdevicePort
U into deUMUR��@�
UtaNthe target task at 
Qaddr
U. This RPC is illegal for native m68k devices.
        !          1294: .UHUR��`�
Q�=devicePort
U is the kernel provided handle for the device.
        !          1295: SHUCUR��`�
Q��Ztarget_task
U represents the address space into which the device page should be mapped.
        !          1296: bU>UR��`�
Q<dVoffset
U is an offset within the device's slot space at which mapping should begin.
        !          1297: |U9UR��`�
QDeNaddr
U is the address in target_task where the slot space should be mapped.
        !          1298: �U4UR�� �
Q��clen
U is the length in bytes of the region to be mapped. The maximum value for (
Qoffset
U + `��U/UR���
Qt Nlen
U) is 0xf00000 (15M) for NRW DMA devices and 0x1000000 (16 M) for other �U*UR��@�
U�  devices.
        !          1299: �U%UR�� �
QWanywhere
U is a boolean, if YES, indicates the kernel may pick any unused address to �U UR��@�
Umap the slot space.
        !          1300: ��&�q��UT`�
[tIOUnmapSlot()
        !          1301: &*UUR��`�
UTb0Remove slot space from a driver�s address space
        !          1302: de&AUUR��`�
Uta&
        !          1303: h&RU
UR��`�
V
Q"#import <driverkit/user_driver.h>
        !          1304: &lUUR��`�
U.
        !          1305: $IODeviceReturn 
VIOUnmapSlot
U(
        !          1306: s &yUUR��`�
Ud #IODevicePort 
QdevicePort
U,
        !          1307: `�&�T�UR��`�
U
U!vm_task_t 
Qtarget_task
U,
        !          1308:  &�T�UR��`�
Uagvm_offset_t 
Qaddr
U,
        !          1309: ��&�T�UR��`�
UUvm_size_t 
Qlen
U);
        !          1310: &�T�UR��`�
Ut DESCRIPTION
        !          1311: sh&�T�UR�� �
VURLIOUnmapSlot
U unmaps the slot space of the NeXTbus device associated with ld&�T�UR��@�
QURrdevicePort
U. 
Qaddr 
Uand 
Qlen
U must match similar fields from a previous call to 
VIOMapSlot
U.
        !          1312: d��0x���MA$6����ot$6���| UR�����UT`�
[ i
IOMapBoard()
        !          1313:  &UNUR��`�
U k/Map board space into a driver�s address space.
        !          1314: ��=UIUR��`�
Usl&
        !          1315: sNUDUR��`�
VUT"#import <driverkit/user_driver.h>
        !          1316: hU?UR��`�
Ulo#IODeviceReturn 
VIOMapBoard
U(
        !          1317: 
        !          1318: deuU:UR��`�
Uta#IODevicePort 
QdevicePort
U,
        !          1319: ive�U5UR��`�
U>
        !          1320: !vm_task_t 
Qtarget_task
U,
        !          1321: n�U0UR��`�
UUvm_offset_t 
Qoffset
U,
        !          1322: �U+UR��`�
UePvm_size_t 
Qlen
U,
        !          1323: ��U&UR��`�
U
0vm_offset_t *
Qaddr
U,/* in/out */
        !          1324: se�U!UR��`�
U��BOOL 
Qanywhere
U);
        !          1325: �UUR��`�
U;
        !          1326: &
        !          1327: ��UUR�� �
VDE]IOMapBoard
U maps the board space of the NeXTbus device associated with 
QdevicePort
U s�UUR��@�
UT�&into the target task at 
Qaddr
U.
        !          1328: &U
UR��`�
Q=devicePort
U is the kernel provided handle for the device.
        !          1329: l&+UUR��`�
QZtarget_task
U represents the address space into which the board space should be mapped.
        !          1330: &EUUR��`�
QWoffset
U is an offset within the device's board space at which mapping should begin.
        !          1331: rd &_T�UR��`�
Qr�Waddr
U is the address in 
Qtarget_task
U where the board space should be mapped.
        !          1332: _dr&yT�UR�� �
Q��clen
U is the length in bytes of the region to be mapped. The maximum value for (
Qoffset
U + U,&�T�UR��@�
Q�len
U) is 0x10000000 (256M).
        !          1333: 
U&�T�UR�� �
Q�Wanywhere
U is a boolean, if YES, indicates the kernel may pick any unused address to UR&�T�UR��@�
U_omap the board space.
        !          1334: &�;��UT`�
[seIOUnmapBoard()
        !          1335: U��T�UR��`�
Uer2Remove board space from a driver�s address space.
        !          1336: T�UR��`�
Uap&
        !          1337: h(T�UR��`�
Vhe"#import <driverkit/user_driver.h>
        !          1338: BT�UR��`�
UU%IODeviceReturn 
VIOUnmapBoard
U(
        !          1339: aOT�UR��`�
UU
#IODevicePort 
QdevicePort
U,
        !          1340: he \T�UR��`�
Und!vm_task_t 
Qtarget_task
U,
        !          1341: �iT�UR��`�
U
Uvm_offset_t 
Qaddr
U,
        !          1342:  ivT�UR��`�
Ud vm_size_t 
Qlen
U);
        !          1343: d�� o���e'$6����ul$6���|  iadURUR��`�
Ut_DESCRIPTION
        !          1344:  tUMUR�� �
VulNIOUnmapBoard
U unmaps the board space of the NeXTbus device associated with %UHUR���
Qhe_devicePort
U. 
Qaddr 
Uand 
Qlen
U must match similar fields from a previous call to �T�2UCUR��@�
UanIOMapBoard.
        !          1345: a g����UT`�
[ndOperational RPC's
        !          1346: �����UT`�
[adIOSendChannelCommand()
        !          1347: @��U6UR��`�
Ud  Issue channel-specific command.
        !          1348: ma�U1UR��`�
UUR&
        !          1349: ��U,UR��`�
Voa"#import <driverkit/user_driver.h>
        !          1350: �U'UR��`�
U�.IOChannelReturn 
VIOSendChannelCommand
U(
        !          1351: &
        !          1352: U"UR��`�
UT�#IODevicePort 
QdevicePort
U,
        !          1353: IOU&UUR��`�
UT�int 
QchannelNumber
U,
        !          1354: t&$UUR��`�
U,%IOChannelCommand 
Qcommand
U);
        !          1355: 
&DUUR��`�
U
        !          1356: �DESCRIPTION
        !          1357: �&UUUR�� �
Vt QIOSendChannelCommand
U is used to issue commands on the DMA channel identified �&bU  UR���
UPby 
QdevicePort
U and 
QchannelNumber
U. CHAN_NONE can be specified for &oUUR���
QKchannelNumber
U if no channels are attached; in this case the only legal  u&|T�UR���
Uac>IOChannelCommand bits are IO_CC_INTR_ENABLE and INTR_DISABLE. &�T�UR��@�
UadCOtherwise it is an error if the device or channel is not attached.
        !          1358:  to&�T�UR��`
Q�=devicePort
U is the kernel provided handle for the device.
        !          1359: �&�T�UR��`&
QIO-channelNumber
U is a local channel number.
        !          1360: s&�T�UR��`
Qic7command
U is the command for the channel to execute:
        !          1361: "#i&�T�UR��`
Use0IO_CC_START_READ -- enable read DMA (68K only)
        !          1362: 
T�UR��`
Uma2IO_CC_START_WRITE -- enable write DMA (68K only)
        !          1363: %T�UR��`
UU@IO_CC_ABORT -- abort current DMA (disables channel) (68K only)
        !          1364: ,?T�UR��`
Und7IO_CC_INTR_ENABLE -- enable interrupts on the channel
        !          1365: UUYT�UR��`
UIO9IO_CC_INTR_DISABLE -- disable interrupts on the channel
        !          1366:  sT�UR�� �
U �GIO_CC_LOOP_FRAME - link current end of DMA frame queue to start of DMA AN_�T�UR���
UieKframe queue. This allows a continuous DMA operation for devices like video in d��UR���lC$6����an$6���| rw) iURUR���
UdeRwithout the need for any software intervention at the completion of a list of DMA UMUR���
U fOframes. Note that once a DMA frame is put into �loop� configuration, no frames .
        !          1367: s!UHUR���
UicCmay be enqueued or dequeued until the frame loop is broken via the ��.UCUR��@�
UTAIO_CC_UNLOOP_FRAME command.
        !          1368: K HU>UR�� �
U��@IO_CC_UNLOOP_FRAME - unlink end of DMA frame queue from head of URUU9UR���
UCCPqueue. This is illegal when the channel is enabled; IO_CR_BUSY will be returned IbU4UR��@�
U- in that case. 
        !          1369:  on|U/UR�� 
UT�3All commands may be OR�d with IO_CC_INTR_ENABLE or rru�U*UR��
U
        !          1370:  AIO_CC_INTR_DISABLE to form compound commands (e.g. IO_CC_ABORT | a�U%UR��
Uof=IO_CC_INTR_DISABLE or IO_CC_START_READ | IO_CC_INTR_ENABLE). u�U UR��
Ufo;Note than on NRW, IO_CC_START_READ, IO_CC_START_WRITE, and �UUR��
UlCMIO_CC_ABORT are done by the driver by directly accessing the channel command w�UUR��@
U��
        !          1371: register.
        !          1372: �g��UT`        
[ aIOEnqueueDma()
        !          1373: ven&U
UR��`
        !          1374: 
Uti*Add a DMA Frame to the current DMA queue.
        !          1375: &'UUR��`
Uce&
        !          1376: D&8UUR��`
Vto"#import <driverkit/user_driver.h>
        !          1377: &RT�UR��`

Uic&IOChannelReturn 
VIOEnqueueDma
U(
        !          1378: &_T�UR��`
Uen#IODevicePort 
QdevicePort
U,
        !          1379: CC_&lT�UR��`
Undint channelNumber,
        !          1380: �&yT�UR��`
UMEtask_t 
Qtask_port
U,
        !          1381: ue&�T�UR��`
UU9vm_offset_t 
Qaddr
U,
        !          1382: is&�T�UR��`
U�vm_size_t 
Qlen
U,
        !          1383: Y&�T�UR��`
UIIODmaDirection 
Qrw
U,
        !          1384: a&�T�UR��`
U��#IODescriptorCommand 
Qcmd
U,
        !          1385: th &�T�UR��`
Uorunsigned char 
Qindex
U,
        !          1386: NTR&�T�UR��`
Uom'IOChannelEnqueueOption 
Qopts
U,
        !          1387: UR&�T�UR��`
UC_unsigned 
Qdma_id
U,
        !          1388: EAD&�T�UR��`
ULEBOOL *
Qrunning
U);
        !          1389: &�T�UR��`
U_C&
        !          1390: T&�T�UR�� 
VARUIOEnqueueDma 
Ubuilds and enqueues a list of DMA descriptors describing a block of cT�UR��
U cYmemory. This block of memory is referred to as a 
Vframe
U. The frame may cross page �T�UR��
UA Vboundaries in most cases. The exception is for channels which have been configured as &T�UR��
UerX�streaming mode� channels per 
VIOAttachChannel
U(). Frames for DMA read operations De3T�UR��
UePS(device to memory) for streaming mode channels must not cross page boundaries. The t @T�UR��
Uue\reason for this restriction is that when the device-specific logic signals �End of record�, 
UMT�UR��
UWthe DMA hardware will advance to the next buffer descriptor, not the next frame. There U,ZT�UR��
UOis no way for the hardware to advance to the next frame; frames are a software ptigT�UR��
UURUconstruct. Therefore for such channels, we force one frame to consist of exactly one utT�UR��
UURNDMA descriptor. This does not preclude the use of multiple frames for a given �T�UR��@
Ursstreaming-mode type packet.
        !          1391: URd��f ���as$6����os$6���| n asURUR�� 
UisRThere are system dependent limits to the amount of memory that may be queued with UMUR��
VAtUIOEnqueueDma
U; exceeding this limit will return an error and the data will not be m!UHUR��@
U m
        !          1392: enqueued.
        !          1393: ;UCUR�� (
VgeQIOEnqueueDma
U will return IO_CR_BUSY if the specified channel is currently in tHU>UR��@(
U��;�DMA Frame Loop� mode (See IOSendChannelCommand(), above).
        !          1394:  habU9UR�� 
Qe aaddr
U must be aligned to the size of the device buffer. On m68K machines, 
Qlen
U must be  oU4UR��
Ue Va multiple of the device buffer length for all descriptors with IO_CEO_EOR not set in |U/UR��
Uweathe 
Qopts
U argument. On m88k machines, 
Qlen
U must be a multiple of the device buffer c�U*UR��@
Ult length for DMA read operations.
        !          1395: ���U%UR��`
Ug-CChains of DMA frames will be limited to some length by the kernel.
        !          1396: ��U UR��`
Q=devicePort
U is the kernel provided handle for the device.
        !          1397: �UUR��`
QUR-channelNumber
U is a local channel number.
        !          1398:  �UUR��` 
Qem:task_port
U is the task where DMA will be done to/from.
        !          1399: &UUR��`!
QthHaddr
U is the address in the current task where the DMA should begin.
        !          1400:  m&%UUR��`"
QURDlen
U is the length of the DMA in the target tasks address space.
        !          1401:  c&?UUR�� #
Qy Orw
U is the direction of the DMA, either IO_DMA_DIR_READ (from the device to e).&LUUR��@#
U9memory) or IO_DMA_DIR_WRITE (from memory to the device).
        !          1402: f&fT�UR��`$
Qne8cmd
U is a NRW channel descriptor command (m88k only)
        !          1403: f &�T�UR��`%
Qle[index c
Uontains the region and register index to which cmd will be written (m88k only).
        !          1404: gum&�T�UR��`&
Qne[opts
U are channel options that should apply to the frame being enqueued. These include:
        !          1405: rea&�T�UR�� '
UU%JIO_CEO_EOR -- the last descriptor in the frame should be indicated as the &�T�UR��@'
UURend-of-record.
        !          1406: ice&�T�UR��`(
Urn<IO_CEO_DESC_INTR -- interrupt when this frame is completed.
        !          1407: ne&�T�UR��`)
Uoc6IO_CEO_ENABLE_INTR -- enable interrupt notification.
        !          1408: T�UR��`*
UDMDIO_CEO_ENABLE_CHAN -- enable DMA channel after enqueue (m68k only).
        !          1409: in)T�UR��`+
UwhBIO_CEO_DESC_CMD -- enable channel descriptor command (m88k only)
        !          1410: CT�UR�� ,
Qth^dma_id
U is an integer, uninterpreted by the kernel, whose sole purpose is to identify this PT�UR��@,
UfrVframe when 
VIODequeueDma
U()'d. 
Qdma_id
U must not be equal to DMA_ID_NULL.
        !          1411: jT�UR�� -
QUR[running
U is returned; on the m68k this indicates whether the channel was enabled at the [inwT�UR��-
UheStime of the enqueue (if not, a channel enable will be required). On the m88k, this `&�T�UR��-
U cYindicates whether or not the transfer engine had a non-empty descriptor list at the time �d��es���ho$6������$6���| ( IOURUR��-
UinZof the enqueue. If on the m88k 
Qrunning
U is NO, a Load Descriptor operation will be UMUR��@-
Uti necessary to start the channel.
        !          1412: NAI����UT`.
[ DIODequeueDma()
        !          1413: enqgUDUR��`/
Uin/Dequeue DMA frames from the current DMA queue.
        !          1414: cha~U?UR��`0
Umm&
        !          1415:  �U:UR��`1
VUR"#import <driverkit/user_driver.h>
        !          1416: �U5UR��`2
Uby&IOChannelReturn 
VIODequeueDma
U(
        !          1417: �U0UR��`3
UUR#IODevicePort 
QdevicePort
U,
        !          1418: eDm�U+UR��`4
U_iint 
QchannelNumber
U,
        !          1419: I�U&UR��`5
U��'IOChannelDequeueOption 
Qopts
U,
        !          1420:  m6�U!UR��`6
Uwhvm_size_t *
Qbcount
U,
        !          1421: t�UUR��`7
U��(IOChannelStatus *
Qchan_status
U,
        !          1422: ha�UUR��`8
Ue #IODmaStatus *
Qdma_status
U,
        !          1423: UR&UUR��`9
UcaBOOL *
Qeor
U,
        !          1424: t&U
UR��`:
U aunsigned *
Qdma_id
U);
        !          1425: h&1UUR��`;
UDESCRIPTION
        !          1426: &BUUR�� <
V�CIODequeueDma
U dequeues a single DMA frame which was enqueued by &OT�UR��<
V(`IOEnqueueDma
U. It will only dequeue frames that meet the criteria specified in 
Qopts
U. to&\T�UR��<
Ue SIt unlocks the associated memory. It returns an indication if more descriptors are ueD&iT�UR��@<
U��8available to dequeue by the criteria specified in opts.
        !          1427: ha&�T�UR�� =
VmmOIODequeueDma
U will return an error (IO_CR_BUSY) if the IO_CDO_ALL option is &IO&�T�UR��=
UIOSspecified, the channel is running, and no completed frames are available. In other ��&�T�UR��=
UQTwords, it is not possible to dequeue non-completed descriptors while the channel is U!&�T�UR��@=
U        running.
        !          1428: &�T�UR�� *
VUVIODequeueDma
U will also return IO_CR_BUSY if the specified channel is currently in &�T�UR��@*
Uta;�DMA Frame Loop� mode (See IOSendChannelCommand(), above).
        !          1429: UR&�T�UR��`)
Usi&
        !          1430: dT�UR��`>
Q
        !          1431: h=devicePort
U is the kernel provided handle for the device.
        !          1432: uT�UR��`?
Qs /channelNumber
U is a logical channel number.
        !          1433: UR9T�UR��`@
Qqu=opts
U are options to 
VIODequeueDma
U, these include:
        !          1434: sST�UR��`A
Uts.IO_CDO_DONE -- dequeue only completed frames.
        !          1435: mT�UR��`B
U r"IO_CDO_ALL -- dequeue all frames.
        !          1436: d��av���th$6����T�$6���| tu erURUR��`C
Uf 1IO_CDO_ENABLE_INTR -- enable interrupt messages.
        !          1437: p!UMUR�� D
UelJIO_CDO_EI_IF_MT -- re-enables device interrupts for the device if no more .UHUR��@D
Ut frames may be dequeued.
        !          1438:  nHUCUR��`E
Uip The flags may be OR�d together.
        !          1439: URbU>UR�� F
Qin[bcount
U (returned) is the byte count of actually transferred data. It is only valid for el oU9UR��@F
UT�Ptransfer from the device into memory (i.e. DMA reads). Zero returned on writes.
        !          1440: T��U4UR�� G
Q
        !          1441: d]chan_status
U is the channel descriptor status (only valid for m88k). It is only valid for ��U/UR��G
UumTtransfer from the device into memory (i.e. DMA reads). Zero returned on writes. The 
�U*UR��@G
U, *meaning of this field is device-specific.
        !          1442: �U%UR�� H
Qnl\dma_status
U is machine-independent and indicates the current state of the channel (e.g., ��U UR��@H
U/running, idle, underrun). Only valid for m68k.
        !          1443: �UUR�� I
Q]eor
U is an end of record indication (only valid for certain device and only valid on �DMA t�UUR��@I
U,read� transactions). NO returned on writes.
        !          1444: vi&UUR�� J
Qth^dma_id
U is an integer, uninterpreted by the kernel, whose sole purpose is to identify this &UUR��J
Uge]frame to the device driver. 
Qdma_id
U matches the dma_id of a frame previously enqueued a&%UUR��J
Uid]via 
VIOEnqueueDma
U. If 
Qdma_id 
Uis DMA_ID_NULL, no descriptors are available for n&2UUR��J
UU4Ndequeueing. (This is not an error - that is, 
VIODequeueDma
U will return &?T�UR��@J
UlyIO_CR_SUCCESS in this case.)
        !          1445: m&t�N��UT`n
[e Privileged RPC�s
        !          1446: (&�T�UR�� Q
UerWFrom User level, these RPCs are only executed by the Config program. Some of these are c.
        !          1447: &�T�UR��Q
UnlXalso executed by Kernel-level drivers directly. The usage of these RPCs is described in g.&�T�UR��@Q
UH]detail in the section entitled �Autoconfiguration�. These RPC are listed here for reference.
        !          1448:  &ު;��UT`R
[onIOGetDeviceType()
        !          1449: &�T�UR��`S
Uly>Determine IOSlotId and IODeviceType for a given deviceNumber.
        !          1450: T�UR��`T
Uvi&
        !          1451: $T�UR��`U
Vdm"#import <driverkit/user_driver.h>
        !          1452: >T�UR��`W
Uho(IODeviceReturn 
VIOGetDeviceType
U(
        !          1453: URKT�UR��`X
Ue  port_t 
Qdevice_master
U,
        !          1454: UXT�UR��`Z
Ud 'IODeviceNumber 
QdeviceNumber
U,
        !          1455: ��eT�UR��`\
UIO.IOSlotId *
QslotId
U,// returned
        !          1456: rT�UR��`^
Ure6IODeviceType *
QdeviceType
U,// returned
        !          1457: T�UR��`
Uth*BOOL *
Qin_use
U;// returned
        !          1458: d�� t���UT$6����UR$6���| ar eURUR��`_
UfiDESCRIPTION
        !          1459: e UMUR��  
UT�LConfig uses this RPC to during the initial autoconfiguration process to map  t%UHUR�� 
UibSIODeviceNumbers to device types. The 
Qin_use
U parameter is returned YES if a se 2UCUR�� 
Ue `devicePort currently exists for 
QdeviceNumber
U. This would be the case if an Kernel level nd?U>UR��@ 
UOdriver attached to 
QdeviceNumber
U prior to User level autoconfiguration.
        !          1460: kitt����UT`a
[T�IOCreateDevicePort()
        !          1461: i�U5UR��`e
UDeCreate a devicePort.
        !          1462: R�U0UR��`h
Urt&
        !          1463: �U+UR��`j
VU"#import <driverkit/user_driver.h>
        !          1464: �U&UR��`k
Uum#IODeviceReturn IOCreateDevicePort(
        !          1465: OSl�U!UR��`l
UU port_t 
Qdevice_master
U,
        !          1466: ^�UUR��`m
Upetask_t 
Qtarget_task
U,
        !          1467: �UUR��`n
U��#IODeviceNumber 
QdeviceNumber,
        !          1468: &UUR��`o
U%IODevicePort *
QdevicePort
U);
        !          1469: �&(U
UR��`p
UDESCRIPTION
        !          1470: &9UUR�� 
UTThis RPC causes the kernel to create a devicePort for a specified deviceNumber. The UR&FUUR��
UigYnew devicePort is created in 
Qtarget_task
U�s port space. This RPC returns an error b&ST�UR��@
UtoH(IO_DR_EXISTS) if a devicePort for 
QdeviceNumber
U already exists.
        !          1471: UR&��O��UT`c
[ceIODestroyDevicePort
        !          1472: fo&�T�UR��`g
U
Destroy a devicePort.
        !          1473: &�T�UR��`"
Uve&
        !          1474: d&�T�UR��`#
V"#import <driverkit/user_driver.h>
        !          1475: &�T�UR��`$
Ur ,IODeviceReturn 
VIODestroyDevicePort
U(
        !          1476: T�&�T�UR��`%
Urtport_t 
Qdevice_master,
        !          1477: teT�UR��`&
UU0$IODevicePort 
QdevicePort
U);
        !          1478: U"T�UR��`'
UitDESCRIPTION
        !          1479: >
        !          1480: 3T�UR�� (
UumbThis RPC causes all current state associated with the specified 
QdevicePort
U to be deleted. @T�UR��(
UMAny pending DMAs will be dequeued; registered interrupts will be deleted and mMT�UR��@(
U��
        !          1481: disabled.
        !          1482: d��
        !          1483: ����DE$6����Th$6���|ePr ����UT`a
[Nu
        !          1484: IOInquire
        !          1485: &UNUR��`,
Uig@Determine IOUnitName and IOUnitType for specified IOUnitNumber.
        !          1486: hi=UIUR��`.
Urr&
        !          1487: bNUDUR��`/
Vto"#import <driverkit/user_driver.h>
        !          1488: hU?UR��`0
U
U"IODeviceReturn 
VIOInquire
U(
        !          1489: uU:UR��`1
Uicport_t 
Qdevice_master,
        !          1490: De�U5UR��`2
U.
        !          1491: IOUnitNumber 
Qunit
U,
        !          1492: R�U0UR��`3
Uor;IOUnitType *
QdeviceType
U;              // returned
        !          1493: urn�U+UR��`4
Uce8IOUnitName *
QdeviceName
U);          // returned
        !          1494: er�U&UR��`5
U&DESCRIPTION
        !          1495: ce�U!UR�� 6
UtVThis RPC is used to determine the charactersistics of an arbitrary global kernel unit �UUR��6
UatQnumber (IOUnitNumber). Each instance of each IODevice subclasss in the kernel is e�UUR��6
U dQassigned a unique IOUnitNumber. This RPC and the IOLookup() RPC (below) are used 
        !          1496: �UUR��@6
U�9to determine the characterstics of kernel-level drivers.
        !          1497: �&U
UR��`7
U&
        !          1498: &C�^��UT`8
[ IOLookup
        !          1499: &aUUR�� 9
U��4Determine IOUnitNumber and IOUnitType for specified e &nT�UR��@9
UniIOUnitName.
        !          1500: if&�T�UR��`;
Uhi&
        !          1501: I&�T�UR��`<
V
        !          1502: b"#import <driverkit/user_driver.h>
        !          1503: &�T�UR��`=
U>
        !          1504: !IODeviceReturn 
VIOLookup
U(
        !          1505: n&�T�UR��`>
U(
        !          1506: port_t 
Qdevice_master,
        !          1507:  &�T�UR��`@
UDeIOUnitName 
Qname
U,
        !          1508: tNu&�T�UR��`:
UUR>IOUnitNumber *
Qunit
U;                     // returned
        !          1509: &�T�UR��`A
Urn8IOUnitType *
QdeviceType
U);          // returned
        !          1510:   T�UR��`B
UerDESCRIPTION
        !          1511: 5T�UR�� C
UcePThis RPC is used to determine the charactersistics of a kernel device, given an it"T�UR��C
U uOIOUnitName. This RPC and the IOInquire() RPC (above) are used to determine the ubc/T�UR��@C
Ul (characterstics of kernel-level drivers.
        !          1512: e d��oo���us$6����mi$6���|er
U
����UT`-
[
        !          1513: IOKernDeviceLookup
        !          1514:        IO&UNUR��`?
U��6Obtain id of a kernel IODevice given its IOUnitName..
        !          1515: =UIUR��`E
U��&
        !          1516: 9NUDUR��`F
Vif"#import <driverkit/kern_driver.h>
        !          1517: hU?UR��`G
U<d+IODeviceReturn 
VIOKernDeviceLookup
U(
        !          1518: !IOuU:UR��`H
UOLIOUnitName 
Qdevice_name,
        !          1519: �U5UR��`I
UicEid *
QdeviceId);             
U                    // returned
        !          1520: R�U0UR��`L
U#DESCRIPTION
        !          1521: un�U+UR��`M
U  6THIS FUNCTION IS ONLY AVAILABLE INSIDE OF THE KERNEL.
        !          1522: �U&UR�� D
U);UThis function provides a simple mapping of IOUnitName to id. It�s a rudimentary form R�U!UR��D
UrmTof a future remote object name-to-id mapping mechanism. Since this is only valid in me�UUR��D
U IUthe kernel, no security mechanism is provided; any kernel code can get the id of any s�UUR��@D
Urikernel IODevice.
        !          1523: d������$6����$6���| ��#UT
        !          1524: ��
        !          1525: ��UUhK
[vi&k
ZAutoconfiguration
        !          1526: B����UT`V
[ aUser Level Autoconfiguration
        !          1527: i]UMUR�� P
U��UThis section describes the mechanism by which user-level device drivers are bound to djUHUR��@P
U
VAspecific device registers and DMA channels at system boot time. 
        !          1528: d�������`Y
\URGeneral Scheme
        !          1529: d *�U@UR�� [
U  UThere exists one user-level task, called Config, which is executed early in the boot R�U;UR��[
U FOsequence. Config is a privileged task; it communicates with the kernel via the on �U6UR��[
UmaZdevice_master port. This port is currently obtained via a trap which can only be executed �U1UR��[
U mdby tasks with root privilege. Drivers themselves are 
Vnot
U privileged. (This is a key concept m �U,UR��[
UerYin the NRW Device Driver architecture - User-level device drivers are regular User level ��U'UR��[
UZexecutables with no special privileges whatsoever.) It is Config's job to examine various &U"UR��[
U��^device registers and determine which device drivers, each of which is an executable file, are &UUR��@[
U��/to be associated with which device registers. 
        !          1530: ser&.UUR�� ]
UerbEach logical set of device registers (e.g., all of the SCSI registers) are associated with a port &;UUR��]
UY\called devicePort, which is created by the kernel. devicePort is the basic means by which a  w&HUUR��]
Uar^device driver gains access to a device. Config obtains the devicePort for each device via the &UU UR��]
UheWIOCreateDevicePort() RPC (see the section entitled �Kernel Level Driver Support� for a whi&bUUR��]
UcuZdescription of this RPC as well as all of the other Kernel-Level RPCs referred to in this &oT�UR��]
Us Wsection.) After obtaining the devicePort for a specific device, Config then exec's the dev&|T�UR��]
UguYappropriate driver for that device and makes devicePort available to that driver via the t&�T�UR��]
Uo _bootstrap server, thus enabling the driver to gain access to the registers and other resources f w&�T�UR��@]
Ublassociated with the device.
        !          1531: ��&�������``
\ w,Mapping Device Registers to Device Drivers 
        !          1532: ]&�T�UR�� b
U s^A logical device is a set of registers which are associated with one device (e.g., all of the &�T�UR��b
UevWregisters associated with the SCSI port). Each logical device has associated with it a UR&�T�UR��b
UceTdeviceNumber by which Config refers to it; deviceNumber is machine-dependent but is e T�UR��@b
Uhe6basically an index into an array of logical devices. 
        !          1533: &T�UR�� d
USuUEach logical device also has a 32-bit attribute called IODeviceType. The 16 msb's of e3T�UR��d
Us ZIODeviceType are called deviceIndex; the 16 lsb's are a revision number. For the purposes @T�UR��d
Uig\of this discussion, there are three basic types of devices. One is the type of device which orMT�UR��d
Ut Zconforms to the NRW model of 8 devices per NextBus slot; this device is referred to as an ZT�UR��d
Vrs`NRW DMA Device
U. Another type of device is a 
VNative m68k Device
U, which describes all MagT�UR��d
UteWdevices implemented internally on an m68k CPU board. The other type of device occupies h atT�UR��d
U o`an entire NextBus slot; this is a 
VSlot Device
U. Third party boards for m88k machines can og�T�UR��d
UsoZcontain either one Slot Device or up to eight NRW DMA Devices; third party boards for the d��e ���ba$6����lo$6���|  l( dURUR��d
U2-Rm68k contain one Slot Device (since no DMA is available for NextBus boards on the UMUR��d
UceNm68k). The kernel determines which type of device a NextBus board contains by !UHUR��d
Uon[examining the IOSlotId field of the board. If bits 9 through 7 (inclusive) of the IOSlotId Ut .UCUR��d
UNRYfield are 1, then the board is assumed to contain NRW DMA Devices; otherwise it contains s;U>UR��d
UUPone Slot Device. Native devices on both machines, by convention, are assigned a T�HU9UR��@d
Ude(hard-coded IOSlotId of NATIVE_SLOT_ID. 
        !          1534: U bU4UR�� f
UypNThere is one more significant difference between NRW DMA Devices, Native m68k oU/UR��f
U.WDevices, and Slot Devices; that is in the type and range of memory which can be mapped  De|U*UR��f
Ut Yin by the driver. The various ranges of memory which can be mapped in by various drivers ��U%UR��f
U`is described in the section entitled �Kernel Level Driver Support�. Suffice it to say here that 2-�U UR��f
U SVConfig neither knows nor cares about any of this memory space; mapping and allocating �UUR��@f
UteEthis memory is performed by RPCs between the drivers and the kernel.
        !          1535: d�UUR�� u
Ue VConfig obtains IODeviceType and IOSlotId for a given deviceNumber from the kernel via �UUR��u
Ud Uthe IOGetDeviceType() RPC. It is the responsibility of machine-dependent code in the >�UUR��u
UonXkernel to map deviceNumber to a IOSlotId and IODeviceType. This is done in one of three ���UUR��@u
Uedways:
        !          1536: �UUR�� v
UD.MThe IODeviceType for NRW DMA Devices is obtained from the hardware. A simple D&T�UR��@v
U mMalgorithm maps deviceNumber to the hardware address containing IODeviceType.
        !          1537: n&%T�UR�� x
UURQThe IODeviceType for Native m68k devices is faked by the kernel; the kernel must y&2T�UR��@x
UedOmaintain a hard-coded map of deviceNumber to IODeviceType for native devices. 
        !          1538: d �<�UR�� z
Ur VThe IODeviceType field for Slot Devices is defined as -1; the significant information &YT�UR��@z
UthE(as far as device drivers and Config are concerned) is in IOSlotId. 
        !          1539: r&sT�UR�� �
URPQOnce Config determines the IODeviceType for a given deviceNumber (and assuming a c&�T�UR���
U fRvalid IOSlotId and IODeviceType), it obtains a devicePort for that device via the &�T�UR���
U rVIOCreateDevicePort() RPC. Config must then locate a device driver which is capable of &�T�UR���
UotZdealing with this particular IODeviceType or IOSlotId. This information is encoded in the &�T�UR���
UviYfilename of every executable driver in the (TBD) device driver namespace (for now, let's l&�T�UR���
UeNUassume some Unix directory). The filenames of all of these drivers are of one of the i&�T�UR��@�
Um6following two formats:
        !          1540: e k&�T�UR��`�
Umu2devr_<DEV_INDEX>_<REVISION>_<human_readable_name>
        !          1541: &�T�UR��`�
U I0devs_<SLOT_ID>_<REVISION>_<human_readable_name>
        !          1542: zT�UR�� �
UTyTThe former is used for drivers for NRW DMA Devices and for Native m68k Devices; the zT�UR���
UevSlatter is for Slot Devices. DEV_INDEX, SLOT_ID, and REVISION are all in ASCII hex. nfi)T�UR���
UODNDEV_INDEX and REVISION are 4 hex characters; SLOT_ID is eight hex characters. 6T�UR���
UicV<human_readable_name> is something like �LaserPrinter�. For example, a printer driver CT�UR���
UnfSmight be named �devr_0002_0011_LaserPrinter�. A frame buffer driver might be named  wiPT�UR��@�
U I�devs_00112233_3456_BigFrame�.
        !          1543: ormjT�UR�� �
Un SWhen Config is looking for a driver to handle IODeviceType �abcdABCD� and IOSlotId verwT�UR���
Uw,O�_slot_�, it follows the following algorithm (DEV_INDEX, SLOT_ID, and REVISION f t�T�UR��@�
UUR1come from the filename of a prospective driver):
        !          1544: md��_<���<h$6�����$6���| da!meURUR��`�
U�VFor 
VNRW DMA Devices
U and for 
VNative m68k Devices
U (IODeviceType != -1):
        !          1545: !UMUR��`�
U�3only filenames starting with �devr_� are eligible.
        !          1546:  an;UHUR��`�
U i#DEV_INDEX must match abcd exactly.
        !          1547: NDEUUCUR��`�
UON9The filename with the highest value of REVISION is used.
        !          1548: �oU>UR��`�
U<hFor 
VSlot Devices
U:
        !          1549: �U9UR��`�
Uin3only filenames starting with �devs_� are eligible.
        !          1550: Unf�U4UR��`�
Ude#SLOT_ID must match _slot_ exactly.
        !          1551: uff�U/UR��`�
U n9The filename with the highest value of REVISION is used.
        !          1552: .�U*UR�� �
U�^If no driver with a filename which matches the above criteria is found, the device is skipped �U%UR��@�
U�_Vand the devicePort for that device is deallocated via the IODestroyDevicePort() RPC. 
        !          1553: �U UR��`�
ULWAssuming a driver is found the match is recorded by Config in a list of the following:
        !          1554: ��&������`�
Itypedef struct {
        !          1555: &"������`�
Itypedef struct {
        !          1556: &.������`�
IURIODevicePort devicePort;
        !          1557: DM&:������`�
IfoIODeviceType deviceType;
        !          1558: (I&F������`�
I:
        !          1559: IOSlotId slotId;
        !          1560: on&R������`�
Iin IODeviceNumber deviceNumber;
        !          1561: UH&^������`�
IDE} entry[many];
        !          1562: a&j������`�
IUCint executable_fid;
        !          1563: &v������`�
Ighchar *executable_file_name;
        !          1564: &�������`�
I<h/* other cruft here */
        !          1565: 
        !          1566: &�T�UR��`�
Iin} dev_entry;
U
        !          1567: a&�T�UR��`�
U aWhere
        !          1568: &�T�UR��`�
U��@devicePort is obtained from the kernel by IOCreateDevicePort().
        !          1569:  n&�T�UR��`�
Uh =deviceType is obtained from the kernel by IOGetDeviceType().
        !          1570: fT�UR��`�
UfiFexecutable_fid is the File ID (inode number or its moral equivalent).
        !          1571: T�UR��`�
U�_Kexecutable_file_name is the name located in the algorithm described above.
        !          1572: rt(9T�UR�� �
U��[This mechanism allows multiple devicePort's to be associated with a single driver. In this ng:FT�UR���
U�Ycase, the namespace containing the device drivers would contain links to one executable, ST�UR���
UceTone link for each additional IODeviceType which that driver can handle. When config OS`T�UR���
U��adetects that a file which it is examining is a link to a file which it had already recorded in a �mT�UR���
Ut \dev_entry, it merely adds the new devicePort to that dev_entry.entry[]. This allows mapping  ozT�UR��@�
U
        !          1573: 
        !          1574: \multiple devicePorts to a single driver. The significance of this will be discussed later. 
        !          1575: ced��y ��� n$6����s $6���| e(T�������`�
\ex'Passing devicePort's to Device Drivers
        !          1576:  or"UOUR�� �
UenZOnce Config has mapped all available devices in the system to their associated executable /UJUR��@�
UURBdrivers it performs the following for each driver to be executed:
        !          1577: IUEUR��`�
UleECreate a bootstrap subset port which will be unique for this driver.
        !          1578: gcU@UR�� �
Us VAdvertise each devicePort associated with that driver with the bootstrap server under pU;UR���
UicSthe bootstrap subset port. The name to be advertised is �dev_port_<deviceNumber>�, ch }U6UR��@�
U aKwhere <deviceNumber> is the device's deviceNumber value, in ASCII decimal.
        !          1579: _en�U1UR�� �
Us WCreate a unique signature port for this driver; advertise this port with the bootstrap \mu�U,UR���
U tXserver under the bootstrap subset port with the name �driverSigPort�. This will be used ��U'UR��@�
UWby Config to authenticate the driver in subsequent RPCs between the driver and Config.
        !          1580: |�U"UR�� �
U��YFork and exec (or task_create or...) the driver; the driver task's bootstrap port is the i�UUR��@�
UvaCbootstrap subset port under which the devicePorts are advertised. 
        !          1581: ���UUR�� �
U��^When a driver starts running, if first obtains its devicePorts by doing a bootstrap_info() on �UUR���
U w[its bootstrap port and then doing bootstrap_look_up() of all services found which have the th &UUR���
Uhe\name �dev_port_*�. The result is the set of all devicePorts to which the driver has access. is&U     UR���
UevLThe driver obtains the IODeviceType and IOSlotId of each devicePort via the ic&&UUR��@�
UASdev_port_to_type() Kernel RPC.
        !          1582: Us &@T�UR�� �
Usi[After this, it is up to the driver to perform the binding and memory mapping of the device Xse&MT�UR���
UtsRregisters and interrupt ports for its devices. This is performed via RPCs such as &ZT�UR��@�
U a3IOMapDevicePage(), IOMapSlot(), and IOMapBoard(). 
        !          1583:  dr&tT�UR�� �
U`Since a driver can obtain access to multiple devicePorts, it is possible for one driver task to  p&�T�UR���
UURWdeal with both multiple device types (e.g., Ethernet and Token Ring) and with multiple UR&�T�UR��@�
UL<instances of the same IODeviceType (e.g., two SCSI ports). 
        !          1584: in&�������`�
\()+Behavior of Config Subsequent to Boot Time
        !          1585: and&�T�UR�� �
UraWOnce the procedure above is complete, Config enters a server loop in which a number of *�.&�T�UR���
U sNRPCs are serviced which pertain to the maintenance of devicePorts and further &�T�UR���
UheB(re-)configuration of the system. Config advertises a port called T�UR���
U_tPCONFIG_SERVER_NAME (a string constant defined in Devices/ConfigPublic.h) in the o T�UR���
Ug Vnmserver by which various tasks in the system can make requests of the Config server. T�UR���
Uhi[These RPCs are described below. Note that Config always maintains the state of all running apB+T�UR��@�
UUR>drivers; it is the central housekeeper for all driver tasks. 
        !          1586: d��ve�����$6����de$6���|  ah ����UT`�
[URIORegisterDriver()
        !          1587: es &UNUR��`�
Uce!Notify Config of driver startup.
        !          1588: �=UIUR��`�
UBe&
        !          1589: iNUDUR��`�
Vqu##import <driverkit/ConfigPublic.h>
        !          1590: UrahU?UR��`�
Ure)IOConfigReturn 
VIORegisterDriver
U(
        !          1591: luU:UR��`�
Ubeport_t 
QconfigPort
U,
        !          1592: P�U5UR��`�
Uic port_t 
QdriverSigPort
U,
        !          1593: vi�U0UR��`�
Ur port_t 
QdriverPort
U);
        !          1594: �U+UR��`�
UstDESCRIPTION
        !          1595: er�U&UR�� �
Ud TThis is performed once by each driver. The purpose is to allow Config to detect the ub�U!UR���
UT�Zdeath of a driver via the notification of port death of driverPort, which is a port owned �UUR���
UURZby the driver. Upon such port death notification, Config is responsible for executing the �UUR���
UT�Uappropriate kernel RPC(s) such as IODestroyDevicePort() which instruct the kernel to �UUR���
URclean up any queued DMA requests and delete any interrupt bindings on devicePort. &&U
UR��@�
UXConfig will then attempt to restart the driver initially associated with devicePort.   
        !          1596: on&6�^��UT`�
[tuIODeleteDriver()
        !          1597: �&TUUR��`�
U��Shut down driver gracefully.
        !          1598: n&kT�UR��`q
UU?&
        !          1599: R&|T�UR��`r
Vnf##import <driverkit/ConfigPublic.h>
        !          1600: uU:&�T�UR��`�
U'IOConfigReturn 
VIODeleteDriver
U(
        !          1601: `�&�T�UR��`�
Udport_t 
QconfigPort
U,
        !          1602: �&�T�UR��`�
U !port_t 
QdriverSigPort
U);
        !          1603: �&�T�UR��`�
UerDESCRIPTION
        !          1604: �&�T�UR�� �
UorXThis allows for the graceful, controlled shutdown of a driver without causing Config to T�&�T�UR���
Ur Trestart the driver. Config merely deletes all of its internal state associated with �&�T�UR��@�
Ur.PdriverSigPort. This is normally invoked by the driver which is being shut down.
        !          1605: URd��PC���ev$6����l $6���| uere����UT`s
[anIODeleteDevice()
        !          1606: s&UNUR��`t
UU
-Relinquish control over a single devicePort.
        !          1607: e=UIUR��`y
U#&
        !          1608: lNUDUR��`{
V d##import <driverkit/ConfigPublic.h>
        !          1609: IOhU?UR��`�
UU'IOConfigReturn 
VIODeleteDevice
U(
        !          1610: ulluU:UR��`�
Uqport_t 
QconfigPort
U,
        !          1611: i�U5UR��`�
Uon$IODevicePort 
QdevicePort
U);
        !          1612: IO�U0UR��`�
UODDESCRIPTION
        !          1613: (�U+UR�� �
U�\This allows a driver to relinquish control over a single devicePort. This is typically used T��U&UR���
UDEUwhen a driver has ownership of multiple devices and wishes to give up some subset of a�U!UR���
UusRthem. A driver which wishes to relinquish control of all of its devices would use �UUR��@�
UatIODeleteDriver().
        !          1614: �UUR�� �
Ur.QNOTE: This function not supported in the current implementation. We�ll see if we R&&UUR��@�
U�really need this...
        !          1615: &6�c��UT`�
[IORescanDriver()
        !          1616: &TU   UR��`�
U$Repeat autoconfiguration procedure.
        !          1617: &kUUR��`w
Us&
        !          1618: n&|T�UR��`|
V
        !          1619: s##import <driverkit/ConfigPublic.h>
        !          1620: rol&�T�UR��`�
Uic'IOConfigReturn 
VIORescanDriver
U(
        !          1621: ��&�T�UR��`�
U<dport_t 
QconfigPort
U);
        !          1622: &�T�UR��`�
UIODESCRIPTION
        !          1623: 
V&�T�UR�� �
U(PThis causes Config to perform the initial autoconfiguration procedure described De&�T�UR���
UePOabove again, skipping deviceNumbers for which it currently has valid mappings.  a &�T�UR��@�
Ush:<Is this safe for any old non-privileged task to invoke?>
        !          1624: d��r ���pl$6����me$6���| dr hi����UT`�
[quIOConfigDevice()
        !          1625: o&UNUR�� ~
Ud ?Attempt to find and launch a driver for specified IOSlotId and QNO3UIUR��@~
UnoIODeviceType.
        !          1626: JUDUR��`�
Unt&
        !          1627: o[U?UR��`�
V R##import <driverkit/ConfigPublic.h>
        !          1628: s..uU:UR��`}
U�'IOConfigReturn 
VIOConfigDevice
U(
        !          1629: U�U5UR��`�
UguconfigPort,
        !          1630: �U0UR��`�
UwIOSlotId slotId,
        !          1631: `|�U+UR��`�
UveIODeviceType deviceType);
        !          1632: UR�U&UR��`�
Unf&
        !          1633: e�U!UR��`�
UDESCRIPTION
        !          1634: T��UUR�� �
UgThis causes Config to search for a device matching the 
QslotId
U and 
QdeviceType
U arguments to �UUR���
Ul Sby successive calls to IOGetDeviceType(). If such a device is found, an executable evi�UUR���
Uh Wdriver for the device is located using the same algorithm described previously and the riv&&U
UR���
UokTdriver is exec'd (or whatever). This is the means by which a driver can be launched &UUR���
USsubsequent to boot time. A combination of IODeleteDriver() and IOConfigDevice() is &UN&UUR���
UAtVthe means by which a new driver can be installed for a given device without rebooting &(T�UR��@�
UUR
the system. 
        !          1635: o&]�O��UT`
[ RKernel Level Autoconfiguration
        !          1636: .h>&xT�UR��`
U}PThis section only applies to the m88k architecture. m68k implementation is TBD.
        !          1637: ,
        !          1638: &�T�UR�� E
UwUAutoconfiguring Kernel level drivers is much simpler than autoconfiguring User level �&�T�UR��@E
UUR.drivers. There are two main reasons for this:
        !          1639: &�T�UR�� n
UigZThere is no concept of �security� for Kernel level drivers. All kernel level drivers have &�T�UR��@n
UbyMfull Kernel privileges and must be trusted as much as all other kernel Code.
        !          1640: e&�T�UR�� �
U�[All Kernel level driver run as part of a single task, IOTask. IOTask is a �Kernel task�, a riv&�T�UR��@�
UokDtask which shares the Kernel�s address space but not its IPC space.
        !          1641: caT�UR�� �
UUSAutoconfiguration of Kernel level device drivers is basically performed by mapping nfiT�UR���
UUSdeviceIndex values, which are obtained from the hardware on a per-device basis, to  wi!T�UR���
UT�WObjective C Class names. This mapping is performed by a static table which is compiled xT�.T�UR��@�
UThinto the kernel. 
        !          1642: b�j����`�
\ch
Driver types
        !          1643: i}T�UR��`�
UBD]For purposes of this discussion, there exist three types of device driver within the Kernel:
        !          1644: rd��UR���wo$6������$6���| � )rnURUR�� �
UAlRDirect Device Drivers. These operate directly on hardware. They get access to the UMUR���
Us Shardware via the IOCreateDevicePort() RPC. An example of a Direct Device Driver is a s!UHUR��@�
U. the SCSIController class. 
        !          1645: riv;UCUR�� �
UokQIndirect Device Drivers. These perform I/O through other drivers, usually Direct �HU>UR���
UigUDevice Drivers. An example of an Indirect Device Driver is the SCSIDisk class, which �UU9UR��@�
Ude+does its I/O via the SCSIController class.
        !          1646: e ooU4UR�� �
UisUPseudo Device Drivers. These do not perform physical I/O on the hardware and are not t|U/UR��@�
Us Uconnected to other drivers. An example of a Pseudo Device Driver would be a VM disk.
        !          1647: i�U*UR�� �
UBDOAll three driver types are enumerated into a static array in the kernel called n t�U%UR��@�
U:internalDevMap[]. This is an array of the following type:
        !          1648: �������`�
Itypedef struct {
        !          1649: �������`�
I�&
        !          1650: �������`�
IURconst char      *className;
        !          1651:  �������`�
Ira$const char      **indirectDevices;
        !          1652: ss�������`�
I��unsigned short  deviceIndex;
        !          1653: �������`�
IC.
        !          1654: &������`�
It } internalDevMap_t;
        !          1655: UH&UUR�� �
UthXThere is one internalDevMap_t for each internal device which has a Kernel-level driver. /O&+UUR���
UveXThe internalDevMap_t maps a class name not only to a deviceIndex but also to all of the  D&8U&UR��@�
Uis7Indirect Device Driver classes which use that device. 
        !          1656: e S&l������`�
\s.Probe methods
        !          1657: &�T�UR�� �
UevXEach of the three driver types must implement a factory �probe� method which is invoked �&�T�UR��@�
U o^during initialization. There are three formats of the probe method, one for each driver type.
        !          1658: &�������`�
Ies/*
        !          1659: enu&�������`�
Iti *
        !          1660: ay &�������`�
Ied; * All probe methods return id of the instantiated driver 
        !          1661: of &�������`�
I:
        !          1662: 2 * on successful initialization; else return nil.
        !          1663: &�������`�
I�� *
        !          1664: `�&�������`�
I  1 * Direct device driver (connected to hardware).
        !          1665:  &�������`�
Ies */
        !          1666: ��������`�
IuE+ probe:(IODeviceNumber)devNumber deviceMaster:(port_t)deviceMaster;
        !          1667:  ������`�
I_t&
        !          1668: H������`�
Ith/*
        !          1669: re $�}����`�
IMa; * Indirect device driver (connected to another IODevice).
        !          1670:  /O0�z����`�
Ive */
        !          1671: in<�w����`�
Is + probe:directDriver;
        !          1672: H�t����`�
I a&
        !          1673:  T�q����`�
IU&/*
        !          1674: ��`�n����`�
I D) * Pseudo device (connected to nothing).
        !          1675:  l�k����`�
I� */
        !          1676: Prx�h����`�
IUR        + probe;
        !          1677: vd��us����p$6����T�$6���| he tURUR�� �
Ue YIn each case, on successful return, the appropriate object(s) have been instantiated and *UMUR���
U�^initialized and should be ready for I/O. A nil return indicates that the driver class can not !UHUR��@�
Uiz*deal with the specified hardware device. 
        !          1678: ;UCUR�� �
U��YEarly in system initialization, a thread in the IOTask scans through all of the possible �HU>UR���
U+ Uhardware device slots in the system. For each NRW DMA device found, internalDevMap[] tUU9UR���
U�\is scanned; if an entry with the same deviceIndex and the current hardware device is found, /ObU4UR���
UveZthe driver class�s -probe:deviceMaster: method is called. If nil is returned, the scan of oU/UR���
U��NinternalDevMap continues; if another entry is found which matches the current |U*UR���
U�[deviceIndex, the associated class�s -probe:deviceMaster: method is invoked; this continues ���U%UR���
UQuntil either a non-nil value is returned from -probe:deviceMaster: or the end of  �U UR���
Urn^internalDevMap[] is reached. The latter case indicates that no Kernel Level driver exists for �UUR���
UI/athe current deviceIndex; in this case, a driver for this device is free to be configured at User e�UUR���
U 
        !          1679: Zlevel by the Config program. In the former (successful) case, the -probe: method for each �UUR���
U �cof the class�s associated indirect drivers is called; the id of the direct driver is passed as the Map�UUR���
Q�^directDriver
U argument. When this procedure is repeated for all hardware devices, one more �UUR���
U�Tscan of internalDevMap[] is made - all drivers with a deviceIndex of DEV_INDEX_NULL e �UUR��@�
U��Ware considered to be pseudo devices; these classes are probed with the -probe method. 
        !          1680: |U*�T�UR��`�
Ude&
        !          1681: ed��be���is$6����UR$6���|  i.rn
        !          1682: ��
        !          1683: ��UUhh
[ic&l
ZCode Examples
        !          1684: 'UQUR�� �
UrnNThis section contains examples of code which implement various algorithms and 4ULUR���
UUTprocedures described elsewhere in this document. These examples can be found in the reAUGUR��@�
U a/Examples/ subdirectory in the DEVICES project.
        !          1685:  prv����UT`�
[erI/O Thread Example
        !          1686: he �U>UR�� �
U eWThis example illustrates the use the thread-based I/O model. The example is a complete  th�U9UR���
U pUexecutable program. The example implements a very simple IODevice called a MyDevice.  �U4UR���
UarTMyDevice creates one I/O thread via IOForkThread(); the main thread passes commands ri�U/UR���
UInY(in the form of cmdBuf_t�s) to the I/O thread by enqueueing cmdBuf_t�s on a queue called a�U*UR���
UthPioQueue (one of MyDevice�s instance variables) and waking up the I/O thread via be�U%UR���
URioQueueLock. The I/O thread performs some work with the cmdBuf_t and notifies the �U UR��@�
UUU3client of I/O complete via the cmdBuf_t�s cmdLock.
        !          1687: NTh�������`�
Is /*
        !          1688: les&������`�
Ile% * ioThread.m - I/O thread example. 
        !          1689: �&������`�
Ies *
        !          1690: rib&������`�
I�H * This example consists of a simple driver class with one I/O thread. 
        !          1691: pl&'������`�
In H * Exported methods are invoked interactively via stdin. These methods 
        !          1692: UR&3������`�
I e< * pass commands to the I/O thread, which performs various 
        !          1693: mp&?������`�
Ith< * trivial tasks and then notifies the exported methods of 
        !          1694: ts&K������`�
Iev * command complete.
        !          1695:  &W������`�
Iar */
        !          1696: vi&c������`�
I t 
        !          1697: &o������`�
I()H#define IOSERVER 1                // temporarily necessary for library 
        !          1698: cm&{������`S
I/O5                                  //   compatibility
        !          1699: *&�������`�
Iio&
        !          1700: u&�������`�
I�s#import <driverkit/IODevice.h>
        !          1701: p t&�������`
Ibe#import <driverkit/libIO.h>
        !          1702: oc&�������`&
Ipe#import <mach/mach.h>
        !          1703: &�������`
Iif#import <kernserv/queue.h>
        !          1704: 3cl&�������`
Ite&#import <driverkit/NXConditionLock.h>
        !          1705: &�������`
Ies&
        !          1706: �&�������`
I *)static void MyDeviceThread(id deviceId);
        !          1707: �&�������`
Iib&
        !          1708: �&�������`
I/*
        !          1709:  ex&�������`
Ia ( * Commands to be passed to I/O thread.
        !          1710: pl������`      
In  */
        !          1711: xp�����`
        !          1712: 
Iintypedef enum {
        !          1713: ly #�|����`
Iet3IOC_GETNUM,            // get a number from stdin
        !          1714:  I//�y����`
Irf*IOC_PRINTNUM,          // print a number
        !          1715: ;�v����`

In  IOC_QUIT               // exit
        !          1716: tsG�s����`
Iev} ioCmd_t;
        !          1717: comS�p����`
I��&
        !          1718: �_�m����`
I��/*
        !          1719: `�k�j����`
I��< * This struct is the means by which exported methods pass 
        !          1720: esw�g����`
Icm * commands to the I/O thread.
        !          1721:    ��d����`
I   */
        !          1722: omd��
        !          1723: u���#i$6������$6���| .h6��������`
I#i&
        !          1724: r������`
I��typedef struct {
        !          1725: i������`
Ieu>id              cmdLock;   // NXConditionLock. Clients await
        !          1726: )������`
I@                              //   completion notification via 
        !          1727: Id5������`
I.                              //   this lock.
        !          1728: A������`
Ind3ioCmd_t         cmd;      // operation to perform
        !          1729:  *M������`
I
        !          1730: (int             aNumber;  // some data
        !          1731: etY������`
I  8queue_chain_t   link;     // for enqueueing on ioQueue
        !          1732: Ie������`
I  } cmdBuf_t;
        !          1733: umq������`!
I
&
        !          1734:  }������`)
I  /*
        !          1735:  //�������`*
I��! * Condition values for cmdLock.
        !          1736: ��������`+
I�� */
        !          1737: �������`,
I��#define CMD_BUSY0
        !          1738:  st�������`-
Iby#define CMD_COMPLETE1
        !          1739: ass�������`.
I&
        !          1740: m�������`/
Ihe/*
        !          1741: thr�������`0
I�� * Simple driver class.
        !          1742: �������`1
I */
        !          1743: �������`2
I#i@interface MyDevice:IODevice
        !          1744: �������`3
I{
        !          1745: &&������`4
I>id ioQueueLock;        // NXConditionLock. Protects ioQueue;
        !          1746: &
������`5
I��<                       //   the ioThread awaits input via 
        !          1747: Cl&������`6
I��(                       //   this lock.
        !          1748:   &%������`7
Iti/queue_head_t ioQueue;  // queue of cmdBuf_t's
        !          1749:    &1������`8
I  IOThread ioThread;
        !          1750: ��&=������`9
I  }
        !          1751: &I������`:
Ier&
        !          1752: o&U������`;
I��/*
        !          1753: ��&a������`<
I  % * Condition values for ioQueueLock.
        !          1754: �&m������`=
Iue */
        !          1755: _t&y������`>
Ir #define QUEUE_EMPTY   0
        !          1756: ��&�������`?
I} =#define QUEUE_FULL    1    // at least one element in queue
        !          1757: /&�������`@
I��&
        !          1758: *&�������`A
Ifo/*
        !          1759: Loc&�������`B
I+ * Initialization.
        !          1760: ��&�������`C
ICM */
        !          1761: 0&�������`D
I-- myDeviceInit;
        !          1762: CO&�������`E
I��&
        !          1763: �&�������`F
I��/*
        !          1764: `/&�������`G
I�� * Exported run-time methods.
        !          1765: &�������`H
I�� */
        !          1766: &�������`J
I��F- (int)getNumber;                    // have I/O thread get a number 
        !          1767:       �}����`I
Iio2                                     // from user
        !          1768: �z����`K
I5G- (void)printNumber : (int)aNumber;  // have I/O thread print a number
        !          1769: ��!�w����`L
I  - free;
        !          1770:   -�t����`M
Ick&
        !          1771:  9�q����`N
Iti/*
        !          1772: eueE�n����`O
I// * Private methods.
        !          1773:   Q�k����`P
I   */
        !          1774: hr]�h����`Q
I��- (cmdBuf_t *)cmdBufAlloc;
        !          1775: ��i�e����`R
I��)- (void)cmdBufFree : (cmdBuf_t *)cmdBuf;
        !          1776: *u�b����`S
Ifo)- (void)cmdBufExec : (cmdBuf_t *)cmdBuf;
        !          1777: t��_����`T
Ir &
        !          1778: dd�������E_$6����en$6���| ��6A������`U
I��@end
        !          1779: B������`V
Iat&
        !          1780: .������`W
IC/*
        !          1781:  *)������`X
ID@ * A regular old Unix-y program to exercise the MyDevice class.
        !          1782: ��5������`Y
I�� */
        !          1783: ��A������`Z
Iti int main(int argc, char **argv)
        !          1784:  *M������`[
IJ{
        !          1785: Y������`\
I; id devId;
        !          1786:    e������`]
Ieachar in_string[40];
        !          1787: �q������`^
I  int aNumber;
        !          1788: }������`_
Ifr
        !          1789: �������``
IK/*
        !          1790: - �������`a
I: C * Create and initialize one instance of MyDevice. Forget devPort
        !          1791: I  �������`b
I�� * for this example.
        !          1792: �������`c
Iue */
        !          1793: ��������`d
IridevId = [MyDevice alloc];
        !          1794: `P�������`e
I��[devId myDeviceInit];
        !          1795:  *)�������`f
I�e
        !          1796: �������`g
Ioi/*
        !          1797: uf�������`h
I)cB * Main I/O loop. We'll invoke the exported methods on myDevice 
        !          1798: �������`i
IT * per user input.
        !          1799: &&������`j
I�� */
        !          1800: &
������`k
I 
        !          1801: &������`l
Iwhile(1) {
        !          1802: &%������`m
I�printf("Main Loop:\n");
        !          1803: &1������`n
I
        !          1804: B!printf("  p  print number\n");
        !          1805: �&=������`o
I��printf("  g  get number\n");
        !          1806: d U&I������`p
Ixe#printf("  q  quit program\n\n");
        !          1807: ��&U������`q
I��printf("Enter Selection: ");
        !          1808: gc,&a������`r
I��gets(in_string);
        !          1809: Y��&m������`s
Iiswitch(in_string[0]) {
        !          1810: ]&y������`t
Iin   case 'p':
        !          1811: ��&�������`u
Imb          /*
        !          1812: �&�������`v
I��3 * Get a number, pass it throught to MyDevice's
        !          1813: ate&�������`w
Ie  * I/O thread for display.
        !          1814: &�������`x
I�� */
        !          1815:  &�������`y
I.
        !          1816: 8   printf("\nEnter number to pass to I/O thread: ");
        !          1817:  [&�������`z
IPgets(in_string);
        !          1818: [&�������`{
I];aNumber = atoi(in_string);
        !          1819: &�������`|
I/ [devId printNumber:aNumber];
        !          1820:  I&�������`}
Iok
        !          1821: break;
        !          1822: &�������`~
Ivi
        !          1823: ��&�������`
I    case 'g':
        !          1824: 
        !          1825:     �}����`�
I��        /*
        !          1826: ��z����`�
I . * Get a number via MyDevice's I/O thread.
        !          1827: !�w����`�
Iin */
        !          1828: Loo-�t����`�
I�� aNumber = [devId getNumber];
        !          1829: be9�q����`�
I��/printf("getNumber returned %d\n", aNumber);
        !          1830: ��E�n����`�
Iin
        !          1831: break;
        !          1832: Q�k����`�
I��
        !          1833: ��]�h����`�
I("   case 'q':
        !          1834: ");i�e����`�
Ir          /*
        !          1835: su�b����`�
I�� * Shut down.
        !          1836: ��_����`�
I]) */
        !          1837: ��d������� $6����t $6���| te4��������`�
I*    [devId free];
        !          1838: .
        !          1839: ������`�
I��exit(0);
        !          1840: ��������`�
I
        !          1841: in)������`�
I t   default:
        !          1842: 5������`�
I��'   printf("**Illegal Selection\n");
        !          1843: ��A������`�
INu
        !          1844: break;
        !          1845: M������`�
I��}
        !          1846: |Y������`�
Iin}
        !          1847: er:e������`�
I��
        !          1848: q������`�
I;
        !          1849: /* NOT REACHED */
        !          1850: }������`�
I}
        !          1851: �������`�
I&
        !          1852: }�������`�
I/*
        !          1853: *
        !          1854: ��������`�
I $ * Implementation of simple device.
        !          1855: O �������`�
I�� */
        !          1856: in�������`�
I��@implementation MyDevice
        !          1857: [�������`�
Ibe&
        !          1858: q�������`�
I/*
        !          1859: tf(�������`�
Id  * Initialization.
        !          1860: E�n�������`�
I */
        !          1861: ;
        !          1862: �������`�
I��- myDeviceInit
        !          1863: ��&&������`�
I c{
        !          1864: &
������`�
I��/*
        !          1865: r&������`�
I��# * Initialize instance variables.
        !          1866: ��&%������`�
I*/ */
        !          1867: &1������`�
I&ioQueueLock = [NXConditionLock new];
        !          1868: &=������`�
Iqueue_init(&ioQueue);
        !          1869: �&I������`�
I
        !          1870: &U������`�
I��/*
        !          1871: �&a������`�
I f * Start up the I/O thread.
        !          1872: &m������`�
I�� */
        !          1873: �&y������`�
I��=ioThread = IOForkThread((IOThreadFcn)MyDeviceThread, self);
        !          1874: "&�������`�
In\&
        !          1875: ;&�������`�
I�/*
        !          1876: &�������`�
I��' * Register with IODevice-level code.
        !          1877: er:&�������`�
I�� */
        !          1878: �&�������`�
I/[super init:nil];
        !          1879: }��&�������`�
I}
        !          1880: [self registerDevice];
        !          1881: ��&�������`�
I/*return self;
        !          1882: &�������`�
Ime}
        !          1883: &�������`�
Ice&
        !          1884:  &�������`�
I��/*
        !          1885: 
        !          1886: in&�������`�
I�� * Run-time methods.
        !          1887: i     �}����`�
I� */
        !          1888: 
        !          1889: q�z����`�
I 
        !          1890: !�w����`�
I�/*
        !          1891:  *-�t����`�
I�n+ * Have I/O thread get a number from user.
        !          1892: I��9�q����`�
I�� */
        !          1893: ��E�n����`�
I��- (int)getNumber
        !          1894: /Q�k����`�
I�{
        !          1895: ]�h����`�
InscmdBuf_t *cmdBuf;
        !          1896: %��i�e����`�
I 
int result;
        !          1897: �d��io����$6����$6���| ��3�������`�
I f
        !          1898: ������`�
I t/*
        !          1899: 
        !          1900: ������`�
I�� * Set up a cmdBuf.
        !          1901: �)������`�
IIO */
        !          1902: e5������`�
I�cmdBuf = [self cmdBufAlloc];
        !          1903: A������`�
I��cmdBuf->cmd = IOC_GETNUM;
        !          1904: ��M������`�
Ist
        !          1905: Y������`�
I c/*
        !          1906: r:e������`�
I��> * Pass the cmdBuf to the I/O thread. On return, the desired
        !          1907: q������`�
Ieg! * number is in cmdBuf.aNumber.
        !          1908: *}������`�
I�� */
        !          1909: ��������`�
I��[self cmdBufExec:cmdBuf];
        !          1910: `��������`�
I��result = cmdBuf->aNumber;
        !          1911: hod�������`�
I�[self cmdBufFree:cmdBuf];
        !          1912: I�������`�
I�return result;
        !          1913: ���������`�
Iav}
        !          1914: �������`�
Ibe&
        !          1915: r�������`�
I��/*
        !          1916: `��������`�
I��# * Have I/O thread print a number.
        !          1917: ���������`�
I�h */
        !          1918: ���������`�
It #- (void)printNumber : (int)aNumber
        !          1919: t r&&������`�
I{
        !          1920: &
������`�
IiocmdBuf_t *cmdBuf;
        !          1921: ��&������`�
I�
        !          1922: &%������`�
I/*
        !          1923: &1������`�
I * Set up a cmdBuf.
        !          1924: �&=������`�
I�� */
        !          1925: �&I������`�
I��cmdBuf = [self cmdBufAlloc];
        !          1926: &U������`�
I��cmdBuf->cmd = IOC_PRINTNUM;
        !          1927: �&a������`�
IelcmdBuf->aNumber = aNumber;
        !          1928: �&m������`�
I =
        !          1929: &y������`�
I��/*
        !          1930: �&�������`�
I��' * Pass the cmdBuf to the I/O thread.
        !          1931:  Pa&�������`�
Ihe */
        !          1932: r&�������`�
Ie [self cmdBufExec:cmdBuf];
        !          1933: ! &�������`�
IBu[self cmdBufFree:cmdBuf];
        !          1934: I��&�������`�
I��       return;
        !          1935: [&�������`�
IdB}
        !          1936: &�������`�
I�&
        !          1937: �&�������`�
I->/*
        !          1938: er;&�������`�
I�& * Have I/O thread shut down cleanly.
        !          1939: &�������`�
Ir */
        !          1940: re&�������`�
I��- free
        !          1941: }
        !          1942:       �}����`�
Ibe{
        !          1943: �z����`�
I��cmdBuf_t *cmdBuf;
        !          1944: `�!�w����`�
Ith
        !          1945: -�t����`�
I��/*
        !          1946: ��9�q����`�
I�� * Set up a cmdBuf.
        !          1947:  E�n����`�
I:  */
        !          1948: uQ�k����`�
I��cmdBuf = [self cmdBufAlloc];
        !          1949: ]�h����`�
If;cmdBuf->cmd = IOC_QUIT;
        !          1950: 
        !          1951: d������&up$6���� $6���| cm2lo������`�
I�
        !          1952: ������`�
IOC/*
        !          1953: NU������`�
I' * Pass the cmdBuf to the I/O thread.
        !          1954: ��)������`�
I�� */
        !          1955: �5������`�
I��[self cmdBufExec:cmdBuf];
        !          1956: e cA������`�
Ihr[self cmdBufFree:cmdBuf];
        !          1957:  M������`�
I�&
        !          1958:  Y������`�
Ic:/*
        !          1959: ];e������`�
I� * Free instance variables.
        !          1960: ;q������`�
I� */
        !          1961: }������`�
I��[ioQueueLock free];
        !          1962: ��������`�
I��
        !          1963: �������`�
I��/*
        !          1964: ���������`�
II/+ * Have superclass take care of the rest.
        !          1965: Ir�������`
I�� */
        !          1966: ��������`&
I��return [super free];
        !          1967: �������`
IBu}
        !          1968: �������`
I��&
        !          1969: ��������`
I��&
        !          1970: ��������`
I�q/*
        !          1971: ���������`
Iup * Private methods.
        !          1972: ��&&������`
I�k */
        !          1973: ��&
������`
I=  
        !          1974: &������`        
I�h/*
        !          1975: ��&%������`
        !          1976: 
I>c) * Create and initialize a new cmdBuf_t.
        !          1977: &1������`
I� */
        !          1978: &=������`
I- (cmdBuf_t *)cmdBufAlloc
        !          1979: &I������`

I{
        !          1980: &U������`
IlocmdBuf_t *cmdBuf;
        !          1981: 
        !          1982: &a������`
IOC
        !          1983: &m������`
I�&cmdBuf = IOMalloc(sizeof(cmdBuf_t));
        !          1984: &y������`
I��*cmdBuf->cmdLock = [NXConditionLock new];
        !          1985: &�������`
I];[cmdBuf->cmdLock lock];
        !          1986: [&�������`
IdB([cmdBuf->cmdLock unlockWith:CMD_BUSY];
        !          1987: ��&�������`
I��return cmdBuf;
        !          1988:  &�������`
Iri}
        !          1989: &�������`
I�&
        !          1990: �&�������`
I��/*
        !          1991: I��&�������`
Iee * Free a cmdBuf_t.
        !          1992: ��&�������`
I� */
        !          1993: /&�������`
I�(- (void)cmdBufFree : (cmdBuf_t *)cmdBuf
        !          1994:  r&�������`
I��{
        !          1995: &�������`
I��[cmdBuf->cmdLock free];
        !          1996: r     �}����`
I��#IOFree(cmdBuf, sizeof(cmdBuf_t));
        !          1997: ����z����`
I
        !          1998: �}
        !          1999: !�w����`
I/*&
        !          2000: �-�t����` 
Iup/*
        !          2001: Pri9�q����`!
I��< * Pass a cmdBuf to the I/O thread and wait for completion.
        !          2002:       E�n����`"
I�� */
        !          2003: 
        !          2004: Q�k����`#
Id (- (void)cmdBufExec : (cmdBuf_t *)cmdBuf
        !          2005: d��- ��c
        !          2006: $6������$6���| ��6OC������`$
I{
        !          2007: ������`%
Ioc/*
        !          2008: f(������`&
I��D * Add the cmdBuf to the ioQueue and let the ioThread know it has 
        !          2009: )������`'
IdL * work to do.
        !          2010: ��5������`(
IdB */
        !          2011: LA������`)
I_B[ioQueueLock lock];
        !          2012: M������`*
Iufqueue_enter(&ioQueue,
        !          2013: }
        !          2014: Y������`+
I�
        !          2015: cmdBuf,
        !          2016: e������`,
I��cmdBuf_t *,
        !          2017: q������`-
IdB  link);
        !          2018: �}������`.
I *&[ioQueueLock unlockWith:QUEUE_FULL];
        !          2019: �������`/
I)c
        !          2020: �������`0
I/*
        !          2021: {
        !          2022: �������`1
I�� * Wait for I/O complete.
        !          2023:        �}�������`2
II */
        !          2024: m�������`3
If_+[cmdBuf->cmdLock lockUntil:CMD_COMPLETE];
        !          2025: `�������`4
I��[cmdBuf->cmdLock unlock];
        !          2026: `!�������`5
IdB
        !          2027: �������`6
Ind  return;
        !          2028: o�������`7
I��}
        !          2029: �������`8
I�k&
        !          2030: �&&������`9
Ioi/*
        !          2031: Buf&
������`:
I)c  * Methods invoked by ioThread.
        !          2032: &������`;
I� */
        !          2033: &%������`<
I 
        !          2034: &1������`=
I/*
        !          2035: &=������`>
I�) * Wait for a work to appear in ioQueue.
        !          2036: 
        !          2037: &I������`?
Ioc */
        !          2038: f(&U������`@
I��- (cmdBuf_t *)waitForCmdBuf
        !          2039: Qu&a������`A
ITh{
        !          2040: &m������`B
I��cmdBuf_t *cmdBuf;
        !          2041:  wo&y������`C
I��
        !          2042: &�������`D
I��& [ioQueueLock lockUntil:QUEUE_FULL];
        !          2043: &�������`E
Iuf&
        !          2044: q&�������`F
Ie,/*
        !          2045: ��&�������`G
I7 * At this point, we still hold ioQueueLock'. Remove 
        !          2046: `-&�������`H
I��" * the first element in ioQueue.
        !          2047: &�������`I
I;
        !          2048:  */
        !          2049: �&�������`J
I��-cmdBuf = (cmdBuf_t *)queue_first(&ioQueue);
        !          2050:  &�������`K
Iplqueue_remove(&ioQueue,
        !          2051: I&�������`L
I��
        !          2052: cmdBuf,
        !          2053: &�������`M
IckcmdBuf_t *,
        !          2054: &�������`N
I��  link);
        !          2055: [     �}����`O
Ilo
        !          2056: `!�z����`P
IdB/*
        !          2057: ��!�w����`Q
Ir= * Release ioQueueLock, updating its condition variable as 
        !          2058: �-�t����`R
Iuf< * appropriate, and return the new cmdBuf to the ioThread.
        !          2059: ��9�q����`S
I */
        !          2060: �E�n����`T
I��if(queue_empty(&ioQueue))
        !          2061: ��Q�k����`U
Iai([ioQueueLock unlockWith:QUEUE_EMPTY];
        !          2062: ��]�h����`V
If(else
        !          2063: i�e����`W
Imd'[ioQueueLock unlockWith:QUEUE_FULL];
        !          2064: IThu�b����`X
IBreturn cmdBuf;
        !          2065: md��_����`Y
I��}
        !          2066: d��oQ��UE$6������$6���| 6At������`Z
Iil&
        !          2067: o������`[
Iem/*
        !          2068: `-������`\
I��" * Notify client of I/O complete.
        !          2069: )������`]
I;
        !          2070:  */
        !          2071: 
        !          2072: �5������`^
I��,- (void)cmdBufComplete : (cmdBuf_t *)cmdBuf
        !          2073: 
        !          2074:  A������`_
Ipl{
        !          2075: M������``
Iue[cmdBuf->cmdLock lock];
        !          2076: Y������`a
I��,[cmdBuf->cmdLock unlockWith:CMD_COMPLETE];
        !          2077: e������`b
I��}
        !          2078: q������`c
I��&
        !          2079: �}������`d
I�w@end
        !          2080: ��������`e
Ias&
        !          2081: o�������`f
Ig /*
        !          2082: ond�������`g
I
        !          2083: �E * The I/O thread. This thread sits around waiting for work to do on
        !          2084:  �������`h
I��* * the ioQueue, then behaves accordingly.
        !          2085: �������`i
Iue */
        !          2086: ���������`j
Iai(static void MyDeviceThread(id deviceId)
        !          2087: ���������`k
If({
        !          2088: �������`l
IWcmdBuf_t *cmdBuf;
        !          2089: unl�������`m
I];char in_string[40];
        !          2090: B�������`n
Imd
        !          2091: &&������`o
I}
        !          2092: while(1) {
        !          2093: &
������`p
IoQ
        !          2094: &������`q
I/*
        !          2095: &%������`r
I * Wait for something to do.
        !          2096: ��&1������`s
IAt */
        !          2097: &=������`t
I��%cmdBuf = [deviceId waitForCmdBuf];
        !          2098: \&I������`u
Iie
        !          2099:  I/&U������`v
I��/*
        !          2100: ]&a������`w
I�� * OK, What's up?
        !          2101: cm&m������`x
IdB */
        !          2102: &y������`y
I��switch(cmdBuf->cmd) {
        !          2103: `&�������`z
IdL    case IOC_GETNUM:
        !          2104: `a&�������`{
IdL
        !          2105:     /*
        !          2106: &�������`|
I3 * Get a number from user, pass back to client.
        !          2107: ��&�������`}
I
        !          2108: � */
        !          2109: ��&�������`~
I��1    printf("MyDeviceThread: Enter number: ");
        !          2110: O&�������`
Iadgets(in_string);
        !          2111: or&�������`�
I��&cmdBuf->aNumber = atoi(in_string);
        !          2112: &�������`�
I.
        !          2113: 
        !          2114: break;
        !          2115: &�������`�
I��
        !          2116: ��&�������`�
Ioi    case IOC_PRINTNUM:
        !          2117: d&�������`�
Ik
        !          2118:     /*
        !          2119:       �}����`�
Ic$ * Just display client's number.
        !          2120: ];�z����`�
I40 */
        !          2121: ��!�w����`�
I��8    printf("MyDeviceThread: cmdBuf->aNumber = %d\n",
        !          2122: -�t����`�
IcmdBuf->aNumber);
        !          2123: 9�q����`�
Ir 
        !          2124: break;
        !          2125: E�n����`�
I��
        !          2126: AtQ�k����`�
I��    case IOC_QUIT:
        !          2127: e]�h����`�
Iuf
        !          2128:     /*
        !          2129: i�e����`�
II/4 * Time to die. First notify client that we got 
        !          2130:  Ou�b����`�
I��# * the command, then terminate.
        !          2131: `y��_����`�
IBu */
        !          2132: 
        !          2133: `d��OC����$6����|$6���| ac
li������`�
I��%[deviceId cmdBufComplete:cmdBuf];
        !          2134: �������`�
IyDIOExitThread();
        !          2135: mbe������`�
I�� 
        !          2136: d)������`�
Ig)}
        !          2137: ��5������`�
I
        !          2138: uf-A������`�
I_s/*
        !          2139: 
        !          2140: M������`�
I.
        !          2141: $ * Notify client of I/O complete.
        !          2142: ��Y������`�
Ioi */
        !          2143: e������`�
I$[deviceId cmdBufComplete:cmdBuf];
        !          2144: ��q������`�
I* }
        !          2145: dis}������`�
Ier
        !          2146: �������`�
I40/* NOT REACHED */
        !          2147: ���������`�
Iri}
        !          2148: d�� %���$6������$6���| ��3At����UT`�
[��#Driver Initialization - User Level
        !          2149: `�#UNUR�� �
U�eZThis is an example of a trivial User Level driver which obtains a set of devicePorts from 0UIUR���
Ud,ZConfig (which is assumed to have launched this executable). No actual I/O is performed in =UDUR���
U��]this example; it just illustrates the relationship between Config and a User Level driver as �JU?UR���
Ude]far as obtaining devicePorts and registering the driver via IORegisterDriver() is concerned. �WU:UR���
U��UThe get_devr_port() function, which does the actual bootstrap_lookup()s necessary to �dU5UR��@�
UclMobtain devicePorts, will probably be added to the IODevice class eventually.
        !          2150: v|������`�
Ite/*
        !          2151: uf]�������`
I� * userDriver.m.
        !          2152: ��������`�
I��) * sample user driver. Exec'd by Config.
        !          2153: ��������`�
I}
        !          2154:  */
        !          2155: �������`�
I 
        !          2156: �������`�
I#import <sys/types.h>
        !          2157: �������`�
I��#import <mach/mach.h>
        !          2158: �������`�
I��#import <servers/bootstrap.h>
        !          2159: �������`�
In #import <servers/netname.h>
        !          2160: ��������`�
Ixa#import <bsd/libc.h>
        !          2161: L�������`�
Iob#import <mach/mach_error.h>
        !          2162: m &������`�
Id,#import <bsd/syslog.h>
        !          2163: d t&������`�
Iis"#import <driverkit/user_driver.h>
        !          2164: &������`�
I��##import <driverkit/ConfigPublic.h>
        !          2165: tra&$������`�
Iip#import <driverkit/IODevice.h>
        !          2166: dri&0������`�
I��&
        !          2167: �&<������`�
Ini#define OUR_DEV_TYPE  0x0999
        !          2168: t&H������`�
Igi#define NUM_DEVICES   2
        !          2169:  �&T������`�
I��&
        !          2170: h&`������`�
Ifu9#define dprint(x,a,b,c,d,e)syslog(LOG_ERR, x,a,b,c,d,e)
        !          2171:  &l������`�
I�&
        !          2172: l&x������`�
Its/static int get_devr_port(port_t *devicePorts, 
        !          2173: ent&�������`�
I��int max_devices,
        !          2174: &�������`�
I *const char *driver_name);
        !          2175: `�&�������`�
Ier&
        !          2176: i&�������`�
Ifi/*
        !          2177: ���&�������`�
I *" * Simple driver class interface.
        !          2178: &�������`�
Ior */
        !          2179: /t&�������`�
I��@interface MyDevice:IODevice
        !          2180: 
        !          2181: &�������`�
I��{
        !          2182: &�������`�
Its?port_t   IOPort;      // interrupt notification received here
        !          2183: ��&������`�
Ior}
        !          2184: &��|����`�
I��- MyDeviceInit;
        !          2185: or�y����`�
I.h&
        !          2186:  �v����`�
Id,@end
        !          2187: r �s����`�
I t&
        !          2188: �,�p����`�
I#i int main(int argc, char **argv)
        !          2189: ��8�m����`�
I#i{
        !          2190: D�j����`�
IgPIOConfigReturn crtn;
        !          2191: P�g����`�
I<dkern_return_t   krtn;
        !          2192: 0��\�d����`�
I
        !          2193: �port_t          configPort;
        !          2194: Uh�a����`�
I
        !          2195: t port_t          driverSigPort;
        !          2196: DEt�^����`�
I��+port_t          devicePorts[NUM_DEVICES];
        !          2197:  dp��[����`�
Isyport_t          driverPort;
        !          2198: �d�����ev$6����$6���| ��6�������`�
I*dint             i;
        !          2199: ��������`�
I��id              myId;
        !          2200: ���������`�
I *char            dev_name[30];
        !          2201: ���)������`�
I *
        !          2202: 5������`�
I��4dprint("driver %s: starting\n", argv[0], 2,3,4,5);
        !          2203: {
        !          2204: A������`�
Its
        !          2205: M������`�
I  /*
        !          2206: teY������`�
I r@ * Get some ports - Config server port, driver bootstrap port.
        !          2207: Dee������`�
I�� */
        !          2208: �q������`�
I��*krtn = netname_look_up(name_server_port,
        !          2209: }������`�
Iin4"",                                   // hostname
        !          2210: {
        !          2211: �������`�
IgPCONFIG_SERVER_NAME,
        !          2212: �������`�
I<d&configPort);
        !          2213:  k�������`�
I��if(krtn) {
        !          2214: t_�������`�
Ior$dprint("%s: can't find %s: %s\n",
        !          2215:   �������`�
IDE9argv[0], CONFIG_SERVER_NAME, mach_error_string(krtn),
        !          2216: C�������`�
I�� 4,5);
        !          2217: p�������`�
Iveexit(1);
        !          2218: �������`�
I}
        !          2219: ��������`�
I+krtn = bootstrap_look_up(bootstrap_port, 
        !          2220: 6�������`�
ISIG_PORT_NAME,
        !          2221: &&������`�
I�&driverSigPort);
        !          2222:   i&
������`�
I�if(krtn) {
        !          2223:   &������`�
I��$dprint("%s: can't find %s: %s\n",
        !          2224: _n&%������`�
I��:argv[0], SIG_PORT_NAME, mach_error_string(krtn), 4,5);
        !          2225: &1������`�
I, exit(1);
        !          2226: A��&=������`�
I
        !          2227: }
        !          2228: ��&I������`�
Ite*port_allocate(task_self(), &driverPort);
        !          2229: &U������`j
I d&
        !          2230: e&a������`k
IDe/*
        !          2231: ��&m������`l
I
        !          2232: �: * Get all of the devicePorts which Config has given us.
        !          2233: &y������`m
I� */
        !          2234: &�������`�
I  8if(get_devr_port(devicePorts, NUM_DEVICES, argv[0])) {
        !          2235: NF&�������`�
I��/*
        !          2236: �&�������`�
IgP * Register with Config.
        !          2237: i&�������`�
I�� */
        !          2238: &�������`�
I: &crtn = IORegisterDriver(configPort,
        !          2239: &�������`�
ICOdriverSigPort,
        !          2240: &�������`�
ItndriverPort);
        !          2241: �&�������`�
I��
if(crtn) {
        !          2242: e&�������`�
I��/dprint("%s: IORegisterDriver: crtn = %d\n",
        !          2243: tn &�������`�
Iargv[0], crtn, 3,4,5);
        !          2244: ��&�������`�
IRTexit(1);
        !          2245: ��    �}����`�
Iri}
        !          2246: Po�z����`�
I��}
        !          2247: I�!�w����`�
I��
        !          2248: -�t����`�
Iri/*
        !          2249: : 9�q����`�
In"4 * Start up a driver instance for each devicePort.
        !          2250: acE�n����`�
In) */
        !          2251: 
        !          2252: Q�k����`
I,  for(i=0; i<NUM_DEVICES; i++) {
        !          2253: 
        !          2254: ]�h����`&
I��myId = [MyDevice alloc];
        !          2255: _sei�e����`
I;
        !          2256: $[myId setDevPort:devicePorts[i]];
        !          2257: ku�b����`
I��[myId setUnit:i];
        !          2258: al��_����`
Its)sprintf(dev_name, "%s%d", argv[0], i);
        !          2259: md��i��Po$6������$6���| gP6 R������`
Ig.[myId setDevName:dev_name];
        !          2260: ������`
I: [myId MyDeviceInit];
        !          2261: er(������`
I��}
        !          2262: `�)������`
IPo
        !          2263: 5������`        
Itn/*
        !          2264: riA������`
        !          2265: 
I�� * Sleep until killed.
        !          2266: 
        !          2267: eM������`
I�� */
        !          2268: rY������`
IrD
        !          2269: while(1)
        !          2270: e������`

I��sleep(1);
        !          2271: q������`
I,4
        !          2272: exit(0);
        !          2273: }������`
I}
        !          2274: �������`
I��&
        !          2275: ��������`
I��/*
        !          2276: `��������`
I��= * look up all of our devicePorts. returns # of ports found.
        !          2277: "�������`�
Iri? * This function will probably be standardized and provided in
        !          2278: Q�k�������`�
If" * the IODevice class eventually.
        !          2279: �������`
I */
        !          2280:  [�������`
Ise/static int get_devr_port(port_t *devicePorts, 
        !          2281: rts�������`
I��int max_devices,
        !          2282: �������`
I��const char *driver_name)
        !          2283: �������`
I[0{
        !          2284: &&������`
Iint i;
        !          2285: &
������`
I�name_array_t service_names;
        !          2286: �&������`
Iunsigned int service_cnt;
        !          2287: |&%������`
I��name_array_t server_names;
        !          2288: ev&1������`
I��unsigned int server_cnt;
        !          2289: &=������`
I��bool_array_t service_active;
        !          2290: &I������`
I��"unsigned int service_active_cnt;
        !          2291: &U������`
Ip kern_return_t krtn;
        !          2292: �&a������` 
I
        !          2293: rint port_index = 0;
        !          2294: w&m������`!
I��
        !          2295: &y������`"
I(krtn = bootstrap_info(bootstrap_port, 
        !          2296: ��&�������`#
I��&service_names, 
        !          2297: ��&�������`$
I�&service_cnt,
        !          2298: ��&�������`%
If &server_names, 
        !          2299: &�������`&
Iun&server_cnt, 
        !          2300: �&�������`'
Iti&service_active, 
        !          2301: an&�������`(
Ide&service_active_cnt);
        !          2302: f&�������`)
Icl"if (krtn != BOOTSTRAP_SUCCESS) {
        !          2303: &�������`*
I��$dprint("%s: bootstrap_info: %s", 
        !          2304: t_&�������`+
Its1driver_name, mach_error_string(krtn), 3,4,5);
        !          2305: �&�������`,
Ihareturn(PORT_NULL);
        !          2306: �&�������`-
I��}
        !          2307: ��   �}����`.
I&
        !          2308: ��z����`/
In/*
        !          2309: ra!�w����`0
I
        !          2310: �D * Search for devr_XXXX_XXXX. Later - versions and deviceIndex via
        !          2311: ��-�t����`1
Irv * dev_port_to_type().
        !          2312: 9�q����`2
It  */
        !          2313: cE�n����`3
IBdprint("%s: service_cnt %d\n", driver_name, service_cnt, 3,4,5);
        !          2314: Q�k����`4
I_c%for (i = 0; i < service_cnt; i++) {
        !          2315: t]�h����`5
I��#ifdef notdef
        !          2316: i�e����`6
I��Adprint("%s: service_name %s\n", driver_name, service_names[i],
        !          2317: ou�b����`7
I�� 4,5);
        !          2318: #��_����`8
Iam#endif notdef
        !          2319: d������er$6����$6���| er2ct������`9
I�� if(strncmp(service_names[i], 
        !          2320: f������`:
Icl0    "dev_port_", strlen("dev_port_")) == 0) {
        !          2321: *������`;
I: "dprint("%s: port %s found\n", 
        !          2322: )������`<
Ir_+driver_name, service_names[i], 3,4,5);
        !          2323: ��5������`=
Itu
        !          2324: T_A������`>
I��/*
        !          2325: M������`?
I�� * Get the devicePort. 
        !          2326: InY������`@
I�� */
        !          2327: D e������`A
IXX,krtn = bootstrap_look_up(bootstrap_port,
        !          2328: ��q������`B
Irvservice_names[i],
        !          2329: }������`C
I2&devicePorts[port_index]);
        !          2330: Bd�������`D
I_cif(krtn) {
        !          2331: �������`E
I, (dprint("%s: bootstrap_look_up: %s",
        !          2332:  i�������`F
I+)+driver_name, mach_error_string(krtn),
        !          2333: ���������`G
Iri
3,4,5);
        !          2334: _�������`H
Ireturn(0);
        !          2335: s[i�������`I
I7}
        !          2336: �������`J
I��
        !          2337: else {
        !          2338: �������`K
I&if(++port_index >= max_devices) {
        !          2339: �������`L
I*dprint("%s: num_devices exceeded\n",
        !          2340: �������`M
Idriver_name, 2,3,4,5);
        !          2341: 9&&������`N
I(sreturn(port_index);
        !          2342: �&
������`O
I  }
        !          2343: &������`P
Ior}
        !          2344: =&%������`Q
I��}
        !          2345: : &1������`R
Ior}
        !          2346: fou&=������ S
I��?dprint("%s: %d devicePorts found\n", driver_name, port_index, ��&I������@S
I��3,4,5);
        !          2347: >&U������`T
I��return(port_index);
        !          2348:  &a������`U
In}
        !          2349: &m������`V
I&
        !          2350: /&y������`W
IA/*
        !          2351: ,&�������`X
Ilo * Simple driver class.
        !          2352: ��&�������`Y
I */
        !          2353: ic&�������`Z
I��@implementation MyDevice
        !          2354: r&�������`[
Id&
        !          2355: �&�������`\
I/*
        !          2356: rtn&�������`]
IE: * Device-specific initialization. Assumes valid devPort.
        !          2357: &�������`^
Ive */
        !          2358: , &�������`_
Ikr- MyDeviceInit
        !          2359: ��&�������``
I,5{
        !          2360: &�������`a
I=dprint("MyDeviceInit: unit %d\n", [self getUnit], 2,3,4,5);
        !          2361: J&�������`b
I��
        !          2362:       �}����`c
Iif/*
        !          2363: t_�z����`d
Ies! * ...initialization code here.
        !          2364: n!�w����`e
I e */
        !          2365: \-�t����`f
IMreturn self;
        !          2366: 9�q����`g
I
        !          2367: 9}
        !          2368: E�n����`h
I&
        !          2369: rQ�k����`i
I
        !          2370: �@end
        !          2371: �d��P��     ��$6����or$6���|  %/ce����UT`�
[iv%Driver Initialization - Kernel Level
        !          2372: S#UNUR��`�
U��LThis example is a trivial Kernel-level Direct Driver class. It illustrates:
        !          2373: V=UIUR��`�
U��$The -probe:deviceMaster: interface.
        !          2374:  *WUDUR�� �
UssOThe use of the IOCreateDevicePort(), IOMapDevicePage(), IOAttachChannel(), and ���dU?UR��@�
U
        !          2375: �IOAttachInterrupt() RPCs.
        !          2376: ~U:UR�� �
UEVTypical initialization of NRW interrupt cause and mask registers using the methods in �U5UR��@�
Ukrthe NRW category of IODevice.
        !          2377: �������`n
I��/*
        !          2378: `a�������`o
Iev * probeAndInit.m.
        !          2379: [se�������`
I,5+ * probe: and init example, kernel driver.
        !          2380: Iif�������`p
I�� */
        !          2381: es�������`q
Iat&
        !          2382:  �������`�
I��/*
        !          2383: `e�������`�
I��< * These are necessary to compile this as a user program...
        !          2384: ���������`�
I��*/
        !          2385: `i&������`r
I#define KERNEL 1
        !          2386: &������`s
I�#define KERNEL_FEATURES 1
        !          2387: &������`t
Ior&
        !          2388: &'������`u
I#import <driverkit/IODevice.h>
        !          2389: ��&3������`v
Ier'#import <driverkit/m88k/IODeviceNRW.h>
        !          2390: ��&?������`w
Imp!#import <mach//mach_interface.h>
        !          2391:  &K������`x
Ill#import <bsd/dev/ldd.h>
        !          2392: �&W������`y
Iev#import <driverkit/libIO.h>
        !          2393: UR&c������`z
Ius&
        !          2394: f&o������`{
IeP%#define MY_DEVICE_CHANNEL          0
        !          2395: e&{������`|
IUR&#define MY_DEVICE_BUFSIZE          32
        !          2396: &�������`}
IE,#define MY_DEVICE_CHAN_INTR_MASK   CI_INTR0
        !          2397: e &�������`~
I u(#define MY_DEVICE_DEV_INTR_MASK    0x80
        !          2398: th&�������`
IIO&
        !          2399: i&�������`�
In@interface MyDevice:IODevice
        !          2400: v&�������`�
Im.{
        !          2401: &�������`�
I,5?port_t IOPort;        // interrupt notification received here
        !          2402: I��&�������`�
I��}
        !          2403: &�������`�
I��&
        !          2404: �&�������`�
I��E+ probe:(IODeviceNumber)devNumber deviceMaster:(port_t)deviceMaster;
        !          2405: .&�������`�
I�- myDeviceInit;
        !          2406: ��&�������`�
Iin&
        !          2407: E������`�
I��@end
        !          2408: ������`�
IEA&
        !          2409: E#�|����`�
It/*
        !          2410: &
        !          2411: /�y����`�
I; * Probe and initialization of direct device, kernel mode.
        !          2412: por;�v����`�
IIO */
        !          2413: NRG�s����`�
I��&
        !          2414: wS�p����`�
Ih/static int myDeviceNum = 0;
        !          2415: ��_�m����`�
I<b&
        !          2416: dk�j����`�
I��@implementation MyDevice
        !          2417: ew�g����`�
I��&
        !          2418: �d��eP��
        !          2419: AN$6����UR$6���| ��6��������`�
IMY/*
        !          2420: CE_������`�
II_: * Probe:deviceMaster: is called out during early system 
        !          2421: ������`�
I��; * autoconfig when the autoconfig module finds a hardware 
        !          2422: evi)������`�
I�> * device with a valid mapping in the internalDevMap[] table.
        !          2423: 5������`�
Iei */
        !          2424: reA������`�
I�D+ probe:(IODeviceNumber)devNumber deviceMaster:(port_t)deviceMaster
        !          2425: eNM������`�
Ivi{
        !          2426: Y������`�
IeM
        !          2427: id myId;
        !          2428: e������`�
I- IODeviceReturn drtn;
        !          2429: q������`�
I��IODevicePort localDevPort;
        !          2430: ��}������`�
I�|char dev_name[20];
        !          2431: 
        !          2432: �������`�
I
        !          2433: �������`�
Iiz/*
        !          2434: of�������`�
Irn * Get a devicePort.
        !          2435: �������`�
I�s */
        !          2436: ��������`�
I��)drtn = IOCreateDevicePort(deviceMaster,
        !          2437: ��������`�
I<bIOTaskSelf(),
        !          2438: ��������`�
Iio
devNumber,
        !          2439: g�������`�
I
        !          2440: �&localDevPort);
        !          2441: �������`�
Iif(drtn) {
        !          2442: �������`�
I6IOLog("MyDevice probe: Can't create devicePort\n");
        !          2443: &&������`�
I��return nil;
        !          2444: &
������`�
I��}
        !          2445: II_&������`�
Ias
        !          2446: &%������`�
Iin/*
        !          2447: y &1������`�
I��< * Instantiate and set common IODevice instance variables.
        !          2448: dw&=������`o
I��$ * These are all IODevice methods.
        !          2449: ng&I������`�
IvM */
        !          2450: b&U������`�
I�myId = [self alloc];
        !          2451: &a������`�
I(I$[myId setDevicePort:localDevPort];
        !          2452: po&m������`�
IeN[myId setUnit:myDeviceNum];
        !          2453: �&y������`�
Imy1sprintf(dev_name, "myDevice%d", myDeviceNum++);
        !          2454: �&�������`�
II [myId setDeviceName:dev_name];
        !          2455: ��&�������`i
Ir +   [myId setDeviceType:"SomeDeviceType"];
        !          2456: ��&�������`�
Iof
        !          2457: &�������`�
I /*
        !          2458: a &�������`�
I��1 * Proceed with device-specific initialization.
        !          2459: O&�������`�
Iev */
        !          2460: e&�������`�
I�return [myId myDeviceInit];
        !          2461: �&�������`�
IvN}
        !          2462: &�������`�
I�&
        !          2463: �&�������`�
I;
        !          2464: /*
        !          2465: ��&�������`�
IdrH * Device-specific initialization. Returns nil on error. Assumes valid 
        !          2466: Po    �}����`�
I�� * devicevPort on entry.
        !          2467: ��z����`�
I} */
        !          2468: ��!�w����`�
I
        !          2469: - myDeviceInit
        !          2470: Iin-�t����`�
I��{
        !          2471: 9�q����`�
IatIODeviceReturn drtn;
        !          2472: E�n����`�
IIODevicePage *dev_page_p;
        !          2473:  ThQ�k����`�
Iceunsigned intr;
        !          2474: ��]�h����`�
I
        !          2475: b
        !          2476: i�e����`�
Im/*
        !          2477: [su�b����`�
I��- * ...Initialize instance variables here...
        !          2478: ]��_����`�
I� */
        !          2479: [d������(d$6����++$6���| Na6_n������`�
I��0IOPort = port_allocate(IOTaskSelf(), &IOPort);
        !          2480: ];������`�
I�
        !          2481: ������`�
I�/*
        !          2482: /)������`�
I�A * Perform one-time only hardware initialization. First set up 
        !          2483: �5������`�
I�� * register pointer.
        !          2484: A������`�
Iit */
        !          2485: �M������`�
I}
        !          2486: +drtn = IOMapDevicePage([self devicePort],
        !          2487: /*Y������`�
I�IOVmTaskSelf(),
        !          2488: e������`�
In.(vm_offset_t *)&dev_page_p,
        !          2489: q������`�
I��YES);
        !          2490:  *}������`�
Itrif(drtn) {
        !          2491: ���������`�
I�w<IOLog("MyDevice: Error on IOMapDevicePage (%d)\n", drtn);
        !          2492: �q�������`�
IIreturn nil;
        !          2493: �������`�
I�}
        !          2494: I�������`�
Iag"[self setDevicePage:dev_page_p];
        !          2495: �������`�
I��
        !          2496: �������`�
I��/*
        !          2497: ��������`�
I��? * Clear and disable interrupts. These are all IODevice(NRW) 
        !          2498: ���������`
I
        !          2499: [
 * methods.
        !          2500: �������`�
I�� */
        !          2501: �������`�
I3intr = [self channelIntrCause:MY_DEVICE_CHANNEL];
        !          2502: &&������`�
INa:[self setChannelIntrCause:MY_DEVICE_CHANNEL cause:intr];
        !          2503: &
������`�
I];5[self setChannelIntrMask:MY_DEVICE_CHANNEL mask:0];
        !          2504: �&������`�
I [self setDeviceIntrMask:0];
        !          2505: e&%������`�
Iir
        !          2506: &1������`�
I��/*
        !          2507: ��&=������`�
Int. * Get a global interrupt and a DMA channel.
        !          2508: &I������`�
IpD */
        !          2509: g&U������`�
I],6drtn = IOAttachInterrupt([self devicePort], IOPort);
        !          2510: &a������`�
Ifsif(drtn) {
        !          2511: ge&m������`�
I�>IOLog("MyDevice: Error on IOAttachInterrupt (%d)\n", drtn);
        !          2512: &y������`�
I"Mreturn nil;
        !          2513: &�������`�
I(%}
        !          2514: , d&�������`�
I��+drtn = IOAttachChannel([self devicePort],
        !          2515: }&�������`�
I�MY_DEVICE_CHANNEL,
        !          2516: a&�������`�
I��,NO,                        // stream mode
        !          2517: �&�������`�
I��MY_DEVICE_BUFSIZE);
        !          2518: &�������`�
Iarif(drtn) {
        !          2519: (N&�������`�
I��<IOLog("MyDevice: Error on IOAttachChannel (%d)\n", drtn);
        !          2520: ��&�������`�
I[sreturn nil;
        !          2521: &�������`�
INN}
        !          2522: &�������`�
INa&
        !          2523: [&�������`�
IrC/*
        !          2524: Y_    �}����`�
Ise2 * ...configure device-specific hardware here...
        !          2525: �z����`�
INE */
        !          2526: 0!�w����`�
I� 
        !          2527: [-�t����`�
IMa/*
        !          2528: 
        !          2529: e9�q����`�
Iir6 * Enable interrupts at the device and kernel level.
        !          2530: E�n����`
Ier# * The are IODevice(NRW) methods.
        !          2531: `�Q�k����`�
I�� */
        !          2532: �]�h����`�
Ita,[self setChanelnIntrMask:MY_DEVICE_CHANNEL
        !          2533: ��i�e����`
Idr*          mask:MY_DEVICE_CHAN_INTR_MASK];
        !          2534: u�b����`�
Ita3[self setDeviceIntrMask:MY_DEVICE_DEV_INTR_MASK];
        !          2535: etu��_����`�
I��
        !          2536: d��d��[s$6����@$6���| �
        !          2537: ������`�
I  /*
        !          2538:  /������`�
I��' * Register with IODevice-level code.
        !          2539: ���������`�
Ii */
        !          2540:  )������`�
I�[super init];
        !          2541: Dev5������`�
Ita[self registerDevice];
        !          2542: ��A������`�
I[sreturn self;
        !          2543: M������`�
INN}
        !          2544: Y������`
I�&
        !          2545: ae������`�
I�@end
        !          2546: /q������`&
I�&
        !          2547: ed�� h��
��$6�����$6���| �q3������UT`�
[leGet/Set Parameters
        !          2548: vic#UNUR�� �
U.
        !          2549: VThe following code fragment shows how a user program would read a parameter from, and 0UIUR���
UtaXwrite an array of parameters to, a kernel device named �SomeDevice0�. The code below is VI=UDUR���
U;
        !          2550: Uusing RPCs provided by the kernel; these RPCs are documented in the section entitled �JU?UR���
UU�Kernel-Level Driver Support�. Bear in mind that the RPCs are mapped on to similarly WU:UR���
UUnamed methods which are applied to an instance with a deviceName of �SomeDevice0� in edU5UR��@�
Ucethe kernel.
        !          2551: ��|������`�
Ii(#define SET_PARAM_NAME  �SomeParameter�
        !          2552: ];�������`�
I�+#define GET_PARAM_NAME  �AnotherParameter�
        !          2553: `��������`�
I;
        !          2554: &#define DEVICE_NAME     �SomeDevice0�
        !          2555: �������`�
I��&
        !          2556: ��������`�
I��*int readWriteParams(port_t deviceMaster, 
        !          2557: �������`�
I�unsigned *paramArray, 
        !          2558: �������`�
I�unsigned paramSize)
        !          2559: �������`�
I�q{
        !          2560: �������`�
I�IODeviceReturn drtn;
        !          2561: vic�������`�
I.
        !          2562: IOUnitNumber unit;
        !          2563: a�������`�
IusIOUnitType deviceType;
        !          2564: a&������`�
IUIIOUnitName deviceName;
        !          2565: a&������`�
I tunsigned returnedCount;
        !          2566: &������`
Ideunsigned returnedInt;
        !          2567: �&$������`�
Iro&
        !          2568: e&0������`
Ihe/*
        !          2569:  &<������`�
IthC  * First find the IOUnitNumber of a device named �SomeDevice0�.
        !          2570: t�.&H������`�
I t */
        !          2571: &T������`�
Iimunit = 0;
        !          2572: UR&`������`�
Id do {
        !          2573: hic&l������`�
In #drtn = IOInquire(deviceMaster,
        !          2574: vic&x������`�
I��unit,
        !          2575: ke&�������`�
I��&deviceType,
        !          2576: _PA&�������`�
Iam&deviceName);
        !          2577: �&�������`�
IPA"if((drtn == IO_DR_SUCCESS) &&
        !          2578: &�������`�
I#d0   (strcmp(DEVICE_NAME, deviceName) == 0)) 
        !          2579: �&�������`�
I��break;// success
        !          2580: &�������`�
I 
        !          2581: unit++;
        !          2582: �&�������`�
Iar%} while (drtn != IO_DR_NODEVICES);
        !          2583: g&�������`�
I��&
        !          2584: �&�������`�
I�� if(drtn == IO_DR_NODEVICES) {
        !          2585:  d&������`�
I��7IOLog(�readWriteParams: SomeDevice0 not found\n�);
        !          2586: OUn&��|����`�
I
        !          2587: areturn -1;
        !          2588: IUI�y����`�
Iic}
        !          2589: 
        !          2590: a�v����`�
I t&
        !          2591:  �s����`�
Iou/*
        !          2592: �,�p����`�
IE  * We found the device; it�s IOUnitNumber �unit�. Send an array  
        !          2593: 8�m����`�
I� * of unsigned ints.
        !          2594: e ID�j����`�
Iev */
        !          2595: P�g����`�
I�.)drtn = IOSetParameterInt(deviceMaster,
        !          2596: �\�d����`�
IUR unit,
        !          2597: �h�a����`�
IicSET_PARAM_NAME,
        !          2598: #t�^����`�
I(dparamSize,
        !          2599: ��[����`�
I��paramArray);
        !          2600: ��d��e,��am$6������$6���| &
        !          2601: ��������`�
I  
if(drtn) {
        !          2602: _������`�
I==4IOLog(�IOSetParameterInt returned %d\n�, drtn);
        !          2603: cc������`�
I�return -1;
        !          2604: 
        !          2605: �)������`�
Iar}
        !          2606: wh5������`�
I_N
        !          2607: CESA������`�
I�/*
        !          2608: �M������`
I��  * Now get one parameter.
        !          2609:  Y������`
I� */
        !          2610: IOe������`
Ims)drtn = IOGetParameterInt(deviceMaster,
        !          2611: �q������`
Irn unit,
        !          2612: y}������`
IGET_PARAM_NAME,
        !          2613: I t�������`
I�1,
        !          2614: �������`
I�&returnedInt,
        !          2615: d�������`

IIO&returnedCount);
        !          2616: d �������`
I��
if(drtn) {
        !          2617: �������`       
Is.4IOLog(�IOGetParameterInt returned %d\n�, drtn);
        !          2618: �������`
        !          2619: 
Ireturn -1;
        !          2620: ,
        !          2621: ��������`
IUR}
        !          2622: ni�������`
I�if(returnedCount != 1) {
        !          2623: t�^�������`
I3IOLog(�IOGetParameterInt: returnCount = %d\n�,
        !          2624: �������`
IreturnedCount);
        !          2625: &&������`
Ireturn -1;
        !          2626: �&
������`
I}
        !          2627: &������`
I
        !          2628: &%������`
I�/*
        !          2629: &1������`
I��  * Success.
        !          2630: IO&=������`
IrI */
        !          2631: d &I������`&
I��return returnInt;
        !          2632: re&U������`�
I��}
        !          2633: d��_N���$6���� $6���|
        !          2634: ��
        !          2635: ��UU`k
Z��Libraries and Header Files
        !          2636: ete'UQUR�� 
U
        !          2637: �_This section describes the various libraries and header files which are currently installed by 4ULUR��@
U3the driverkit project. This is fairly tentative...
        !          2638: urnNUGUR��`
U��XThe latest version of the driverkit project can be found in ~osdev/DRIVERKIT/driverkit.
        !          2639: \n�����UT`
[��
        !          2640: Libraries
        !          2641: �U>UR�� 
U
        !          2642: �`All libraries are installed in /usr/local/lib. There are two basic libraries, libIO and libDev. �U9UR��
UPa]There are several versions of each library, and currently all of them get installed when you �U4UR��
U1;Vdo a �make install� from the DEVICES project. There are 3 degrees of freedom for each �U/UR��@
U��8library, and all 8 combinations are currently supplied:
        !          2643: ���U*UR��`
UtuUser or Kernel level.
        !          2644: �U%UR��`
URELEASE and DEBUG versions.
        !          2645: _N&U UR��`
Um88k or m68k version.
        !          2646: &-UUR��  
UaSo, in all, 16 (!) .a files are installed. The versions of libIO and libDev have the same naming e&:UUR��@ 
U
        !          2647: �Wconventions. In the list below, �<libname>� is either libIO or libDev, as appropriate.
        !          2648: lle&R������`!
I��+<libname>68k.a         m68k User   RELEASE
        !          2649: ly &^������`$
IUG)<libname>68k_g.a       m68k User   DEBUG
        !          2650:  &j������`%
Ica+<libname>68k_kern.a    m68k Kernel RELEASE
        !          2651: ���&v������`&
ILi)<libname>68k_kern_g.a  m68k Kernel DEBUG
        !          2652:  &�������`'
Ius+<libname>88k.a         m88k User   RELEASE
        !          2653: ibI&�������`(
IU9)<libname>88k_g.a       m88k User   DEBUG
        !          2654: s&�������`)
Ian+<libname>88k_kern.a    m88k Kernel RELEASE
        !          2655: u &�������`*
I1;)<libname>88k_kern_g.a  m88k Kernel DEBUG
        !          2656: e&ܪO��UT`,
[gr
Header Files
        !          2657: f&�T�UR�� #
U��TMachine-independent header files are installed in /NextDeveloper/Headers/driverkit. tuT�UR��#
Uev0Machine-dependent header files are installed in nsT�UR��@#
U0/NextDeveloper/Headers/driverkit/{m68k/m88k}/. 
        !          2658: So)������`"
Ia &
        !          2659: ed��ib�� s$6����co$6��|isr 
        !          2660: ��
        !          2661: ��UU`2
Zs Revision History
        !          2662: �%������`5
I<l>24-Sep-91Doug MitchellAdded IOInquire(), IOLookup(),
        !          2663: 1������`K
I   IOKernDeviceLookup().
        !          2664: ��=������`N
I>6&
        !          2665: kI������`J
IelI10-Sep-91Doug MitchellMultitudinous name changes to conform to 
        !          2666:  U������`�
Ius next API guidlelines.
        !          2667:   a������`
I��,Added get/set parameters RPCs and 
        !          2668:   m������`
I��methods.
        !          2669: k_ky������`3
IelFixed misc. typos. 
        !          2670: ;�������`�
In_&
        !          2671:  �������`�
I
        !          2672: e306-Aug-91Doug MitchellFirst Distribution.
        !          2673: U���������`4
Ien&e�Xd�6&exLeftd��&tuRightR��d���ndd��� lld��4d��E&riRightNo1HeadRight
        !          2674: Sod���9&&
        !          2675: eLeftBlankFooter�d���"d���*d���,d���$&d���&��d���(tod���/ 24d���1
        !          2676: d���<upd���>d���@
()d���B
        !          2677: kd���Depd���Guld���I cd���K�d���Muid���Od���Setd���U��d���Wd���Y3d���[ td���]n_d���_06d���ad���c��d���eXd���gLed���i tud���k!d���m" d���o#4d���q$Ed���s%ghd���u&
        !          2678: ed���w'd���y(d���{)d���}*d���+d����,d����-d����.d����/d����0d����1d����2d����3d����4d����5d����6d����7d����8d����9d����:d����;d����<d����=d����>d����?d����@d����Ad���Bd�&�Cd&�Dd&�Ed�Fd�Gd�Hd�Id�Jd     �Kd 
        !          2679: �Ld
        !          2680:       �Md
        !          2681: �Nd
�Od
�Pd
�Qd�Rd�S�
E
$G~~$

�&&@�
U&& 
        !          2682: 1&&�&���&�&FunctVarDescll$

�&&@�
X&&&&�NoteBoldNote:  9�l$
        !          2683: 
        !          2684: �&&@�
U&q;&&&�&�
        !          2685: FctLibrary      LIBRARY\t�FctSynopsisd��$
�&&@�
V&&Pd&
        !          2686: &��&&&�&V&&�&        TableHeadD     TableBody&l$$

�&&@�
X&&A&&^�l&�WarningBold\tWarning:\tBody~~$
�&&@�
U&&d&&
        !          2687: �&�&�&BodyIndented�l$
        !          2688: 
        !          2689: �&&@�
U&&qR&&&�&
        !          2690: FctLibrary      LIBRARY\tFctSynopsisll$

�&&@�
U&&�&&cl&~&�&��&@Bodyll$

�&&@�
X&&&old&&NoteBoldNote:  ;ll$
�&&@�
]&&PctL&
        !          2691: i      GlossTermGlossDefHH$'
�&&@�
[&P
        !          2692: 
&
        !          2693: &2HeadBodyea�&&@�
_&&&&      &v�&�&�
        !          2694: FooterLeft
�&&@�
U&&P&&&&FigureFigureTitlell$�&&@�
U&&P&&
        !          2695: FctSubHeadBodyIndented~~$
�&&@�
V&&p        LI&
        !          2696: &�&��&@
U�&
        !          2697: HeaderFileFunctionll$
�&&@�
V&&P&&
        !          2698: &Troubleshooting&Body$$$'
�&&@�
Z&P&e&
        !          2699: &1HeadBody&&HH$

�&&@�
[&&  Gl
&
        !          2700: &FctHeadShortll$
�&&@�
UC&&a&&&Fig1CaptionDefault   FontC:Figure <n>-<n=1>Body~l$�&&@�
U&&&&&~&��&@
U�&&�&BulletShort�\tll$�&&@�
`C&&Q&&&
        !          2701: ChapterNum
C:Chapter <n>ChapterTitlell$'
�&&@�
\&P&&
        !          2702: &3HeadBodyll$
�&&@�
UC&&a&&&&
        !          2703: FigCaptionDefault   FontC:Figure <n>-<n+>Body��$

�&&@�
U&&
&&�&�&�&
BodyIndented2�~$

�&&@�
UN&&A    Gl&&�&eaho�&�&�&Num1Long
        !          2704: N:<n=1>.\t
        !          2705: NumberLong~l$

�&&@�
U&&&efa&&y~&�&��&@
U�&
        !          2706: BulletLong�\t$$$'
�&&@�
Z&&P&&
        !          2707: &1HeadBodyHH$'
�&&@

[&P
&
        !          2708: &
2HeadnBodyle�~$

�&&@
&
UN&&&&&&�&d�&Bo�&�&NumLong        N:<n+>.\t�&&@

_&&&&&   &<&�v�&�FooterRight
Ull$

�&&@

X&&&&&
TiptBoldTip:  �l$
        !          2709: �&&@

U&&q&&&�&
        !          2710: FctSummary      SUMMARY\t
        !          2711: FctLibraryll$A�&&@

`&p&�&&ChapterTitleBody��$
�&&@

U&& tLo&&�&@&&&&&V&&�&  TableBodyll$A�&&@

`&&p&�&&ChapterTitleBody��$&&&

I&&&       &
        !          2712: CodeExamp3~l$

�&&@
    
U&&ng&&~&��&
_&&�&&&�&
        !          2713: BulletLong�\tHH$'
�&&@
        !          2714: 
[&&Pl
&
        !          2715: &X2HeadBodyll$'
�&&@

\&&P&
        !          2716: &3HeadBodyll$'
�&&@

]&&Py&
        !          2717: 4HeadBody@~l$�&&@


UN&&A&&~&�&��&
U&&�&        Num1Short
        !          2718: N:<n=1>.\tNumberShort�~l$�&&@

UN&&&&&~&
`&&�&��&�&NumShort      N:<n+>.\tTll$
        !          2719: �&&@

U&&q
I&&FctSynopsisSYNOPSIS
        !          2720: HeaderFile��$&&&

I&&  &
        !          2721: CodeExamp2~~$
�&&@

U&$&&�&�&�&BodyIndentedll$

�&&@

U&&&l&3H~&�&�&Body�~$

�&&@

UN&&
        !          2722: &&�&�&��&
U&&�&NumLong        N:<n+>.\t�l$
        !          2723: �&&@

U&q&&u&�&
        !          2724: FctSummary      SUMMARY\t
        !          2725: FctLibraryll$A�&&@

`p&~&&ChapterTitleBodyll$
        !          2726: �&&@

U&q&&FctSynopsispSYNOPSIS
        !          2727: HeaderFileFi�&&@

_&  &v�&CoEx�&�
        !          2728: FooterLeft~~$
�&&@

]&&
        !          2729: �&dy�&ed�&BodyIndented�HZ$'
�&&@

[&@
        !          2730: 
&
        !          2731: &FctHead�
        !          2732: FctSummary~~$
�&&@

V&p&
        !          2733: &�&�&��&
        !          2734: HeaderFileFunctionHZ$'
�&&@

[&&@
        !          2735: 
U
&
        !          2736: &FctHead
        !          2737: FctSummarytS~l$

�&&@

XN&&AA&&~&�&�&�&teStep1Bold
        !          2738: N:<n=1>.\t
        !          2739: NumberBold~~$&&&

I&0    &�&
        !          2740: ad�&Fi�&�&��&@
_�&�&&&& &&2&v�&D&Ex&V&&&&h&
        !          2741: ot&z&&�&&�&&�&�&�&
]&&�&&�&        CodeExamp

�&&@

`ted&&l&@
[~&�&�&Body�~$�&&@

U& 
&&~&�&�&�&�&��&
        !          2742: �&Fi�&nc&&& &&2&�&D&
[&&&V&
U&h&Function
        !          2743: ll$�&&@
 
U&P
&&
        !          2744: FctSubHeadBodyIndented��$

�&&@
!
U&tep&&d�&�&�&
BodyIndented2�~$�&&@
"
U&& &&_~&�&�&�&�&v��&�&�&ot&&& &&2&&D&&V&&&h&Function~l$

�&&@
#
XN&&&&&~&�&
[�&�&StepBold      N:<n+>.\t�

�&&@
)
`&&l&~&�&�&Body$l$

�&&@
*
K2&&l&ncon~&
        !          2745: �&�&Body
U$l$A�&&@
+
`p&&&ChapterTitleBody�&&@
-
_&&  &v�&dyde�&�
        !          2746: FooterLeft�&&@
3
_&&  &&�v�&�FooterRightll$
�&&@
;
U&& &&GlossDef~~$&&&
B
I&     &�&�&�&�&ep�&Bo       �&.\�&&&& &@&2&&D&&V&&h&&z&&�&&�&&�&&�&&�&&�&     CodeExamp
~~$&&&
C
I&&   &
        !          2747: �&�&dy�&
U�&�&�&@�&&&& &&2&&D&&V&teit&h&&z&&�&&�&�&�&
_&&�&&�&&�&    CodeExamp
I
y
O   ��
I&��
J&&Emphasis&���
K&&��
L&&Italic��
M&&BookName��k<
N&/��
P&
        !          2748: &&Boldnw
        !          2749: 
Q&
I���
T&&&Symbol���
U&&��ģ
V&
        !          2750: &.\��ģ
X&
        !          2751: &Bold��ģ
Z&
        !          2752: &
��ģ
[&
        !          2753: &��ģ
\&
        !          2754: &~l
]&
        !          2755:       ��
^&&     Subscript     nw
        !          2756: 
_&���
`&&���
a&&&  Trademark     ���
d&&Superscriptit��
m&& GlossTermCourier   HelveticaSymbolTimeso&RegularRegular
        !          2757: Bold&RegularItalic&����X�̍��g��]e������1��>e��ڇ�&��ĉ-R�Bz�=*���������2�O���&q�?J"9��_G��ԙ3�"*A���Z�!���5e���RӔD�e�!�c�D�H�Aa��ECH;2]�,�����J�8?�&�2G~���㥼Vk��<�Vc���1L�JeĘ[,d����1,�
�����~��L��
        !          2758: G`]Pě�@����"�>RJf����tn�yT�N1�j�c��4DQpC`��D�Tn;�oD�%��lr}���F�4��Y(��ڪ��mh��ys��:�YןEr�� ��+�|��m�3��W�a�x̅�)�I��x���a9U���&��2W���p�T\�
        !          2759: 0p|��  6��F�K��z�M��-��(%X6�5�Nɻ4r�J��a��@9���9˩����Z��n�Y��)��f�G�a4)%X�_c�
�͢:]�������T�4���N^y��U����Ǖ�(2.�J#OD,�)
��
        !          2760: ^���q��"9x-G�����7�Ď�ϐ.m�^L�A������-8/%�X@���@o�0��Y?1xp��q��0`�SS7�ӄ�g�����ag�C"�u�(�
/�6J�P���l��ɝ"���t�>X!`-�P�%NdHV��{Mh���[�/����fR�0iRH߇�Ll�u&!/CV�z
        !          2761: ��-�   ����   ϸ���N~W�$�&�����ij�2�9���|S)��tH��0D-, `y0�Y��y�{���z�#<C�]��O��4�n����o�����J]B�u;���m0�K�?�w��}Z�~���|��b1�A���j�+LH��>;Hz�Hc$#��G��I��kq�ԩQ�ʡl<�~�}0��������#�U�_-Q3����b�JAF1�[>0����1\�F��;�ۑT����$|��tT�H$#Q�;�[��<��

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.