Annotation of driverkit/doc/OLD_NRW/NRWDeviceDriver.frame.backup, revision 1.1.1.1

1.1       root        1: <MakerFile 2.0J>
                      2:    
                      3: 
Aa��@"�&ff&�����HH      $ d&&       &&&&&d&&&&[Footnote*���. � �]&&&&&&�&Zm&�&[&
                      4: &��&�x��*1HeadL2Head&x(IOReturn)devEjectDisk(IOReturn)getPhysParamsj(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)netInputR(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)notifyPortj(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
�
�&>

+�
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^��_
 �&>`
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�
��
�&>�
 �
��
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
Bx
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/10/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��@ 
U�Odriver 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&��Xx�0̍��g��]e��JHX1��>��E0���8�ĉ-R�Bz�=*���������2�O���&R      �"9��_G��ԙ3KAtiA���Z��Nz�5e���RY?�߬e�!�c�D�H�O&��ECH;2�(,�����J������D�2G~���㥼Vk��<�Vc���1L�Jfǘ[,d����1,�
�����~���L��
                   2758: G`]Pě�@����"�RR~����tn�yT�N1�j�c��4DQpC`��D�Tn;�oD�%��lr}���F�4��Y(��ڪ��mh��ys��:�YןEr�����+�|��m�3��Ta�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�NS)��tH��0D-, `y0�Y��y�{���z�#<C�]��N���4�n����o�����J]B�kU���m0�K�?�w��}Z�~���|��b1�A���j�+LH��>;Hz�Hc$#��G��I��kq�ԩQ�J�8Q~�}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.