anchor.diff:  (defconstant +rtl8168-TPPoll-NPQ+ 6 "Normal Priority Queue polling")
   (defconstant +rtl8168-TPPoll-FSWInt+ 0 "Forced Software Interrupt")
   
  +;;; Bits in ISR/IMR.
  +(defconstant +ISR-ROK+ 0 "Receive OK")
  +(defconstant +ISR-RER+ 1 "Receive Error")
  +(defconstant +ISR-TOK+ 2 "Transmit OK")
  +(defconstant +ISR-TER+ 3 "Transmit Error")
  +(defconstant +ISR-RDU+ 4 "Rx Descriptor Unavailable")
  +(defconstant +ISR-PUN/LinkChg+ 5 "Packet Underrun/Link Changed")
  +(defconstant +ISR-FOVW+ 6 "Rx FIFO Overflow")
  +(defconstant +ISR-TDU+ 7 "Tx Descriptor Unavailable")
  +(defconstant +ISR-SWInt+ 8 "Software Interrupt")
  +(defconstant +ISR-TimeOut+ 14 "Time Out. TCTR reached TimerInt")
  +(defconstant +ISR-SERR+ 15 "System Error")
  +
   (defconstant +rtl8168-mtu+ 1536)
   (defconstant +rtl8168-descriptor-size+ 16)
   (defconstant +rtl8168-n-tx-descriptors+ 128)
  
positive.code:     (sync:mailbox-send data (rtl8168-tx-mailbox nic))))
  
  (defmethod nic:statistics ((nic rtl8168))
    (values 0
            0
            0
            0
            0
            0
            0))
  
  (defun tx-descriptors-available-p (nic)
    (not (eql (rtl8168-tx-used-count nic) +rtl8168-n-tx-descriptors+)))
  
  (defun rtl8168-worker (nic)
    (when (not (rtl8168-initialize nic))
      (return-from rtl8168-worker))
    (macrolet ((with-rtl8168-access ((nic) &body body)
                 `(sup:with-device-access ((rtl8168-boot-id ,nic)
                                           (return-from rtl8168-worker))
                    ,@body)))
      (unwind-protect
           (loop
              ;; Wait for something to happen.
              ;; Either an interrupt, a request to send, or the device's boot epoch expiring.
              (if (tx-descriptors-available-p nic)
                  (sync:wait-for-objects (rtl8168-irq-handler nic)
                                         (rtl8168-tx-mailbox nic)
                                         (rtl8168-boot-id nic))
                  ;; Don't look in the TX mailbox if all descriptors are full.
                  (sync:wait-for-objects (rtl8168-irq-handler nic)
                                         (rtl8168-boot-id nic)))
              ;; Perform receive handling. Remove packets from the RX ring
              ;; until there are none left.
              (loop
                 (let ((current (rtl8168-rx-current nic)))
                   (with-rtl8168-access (nic)
                     ;; Acknowledge IRQ.
                     (setf (rtl8168-reg/16 nic +rtl8168-register-ISR+) #b1111)
                     (when (logbitp +rtl8168-descriptor-OWN+ (rtl8168-rx-desc-flags nic current))
                       ;; Current descriptor owned by the NIC, no more packets to receive.
                       ;; Break out of the RX loop.
                       (return)))
                   #+(or)(debug-print-line "RTL8168 receive on " current)
                   ;; Receiving one packet.
                   ;; Allocate a buffer. Try to minimize the amount of work done in a device-access region, hence the dropping in and out.
                   (let ((buffer (make-array +rtl8168-mtu+ :element-type '(unsigned-byte 8))))
                     (with-rtl8168-access (nic)
                       ;; Copy the packet into the receive buffer.
                       (let ((address (+ (rtl8168-rx-bounce-virt nic)
                                         (* current (mezzano.supervisor::align-up +rtl8168-mtu+ 128)))))
                         (dotimes (i (min +rtl8168-mtu+
                                          (ldb (byte 16 +rtl8168-descriptor-Frame_Length+)
                                               (rtl8168-rx-desc-flags nic current))))
                           (setf (aref buffer i) (sys.int::memref-unsigned-byte-8 address i))))
                       ;; Reset the descriptor.
                       (setf (rtl8168-rx-desc-flags nic current) (logior (ash +rtl8168-mtu+ +rtl8168-descriptor-Frame_Length+)
                                                                         (ash 1 +rtl8168-descriptor-OWN+)
                                                                         (if (eql current (1- +rtl8168-n-rx-descriptors+))
                                                                             (ash 1 +rtl8168-descriptor-EOR+)
                                                                             0))
                             (rtl8168-rx-desc-vlan nic current) 0))
                     (nic:device-received-packet nic buffer))
                   ;; Advance Current.
                   (setf (rtl8168-rx-current nic) (rem (1+ current) +rtl8168-n-rx-descriptors+))))
              ;; Transmit handling.
              ;; Recover free descriptors.
              (with-rtl8168-access (nic)
                (loop
                   (when (eql (rtl8168-tx-used-count nic) 0)
                     ;; All pending descriptors processed.
                     (return))
                   (when (logbitp +rtl8168-descriptor-OWN+ (rtl8168-tx-desc-flags nic (rtl8168-tx-tail nic)))
                     ;; Reached the descriptor that the card is processing.
                     #+(or)(debug-print-line "RTL8168 still processing " (rtl8168-tx-tail nic))
                     (return))
                   (decf (rtl8168-tx-used-count nic))
                   (setf (rtl8168-tx-tail nic) (rem (1+ (rtl8168-tx-tail nic)) +rtl8168-n-tx-descriptors+))
                   #+(or)(debug-print-line "RTL8168 transmitted packet on descriptor " (rtl8168-tx-tail nic))))
              ;; Send pending packets.
              (loop
                 (when (not (tx-descriptors-available-p nic))
                   ;; Don't transmit when there are no free descriptors.
                   #+(or)(debug-print-line "RTL8168 not transmitting - no free descriptors.")
                   (return))
                 (let ((to-send (sync:mailbox-receive (rtl8168-tx-mailbox nic) :wait-p nil))
                       (current (rtl8168-tx-current nic)))
                   (when (not to-send)
                     (return))
                   #+(or)(debug-print-line "RTL8168 transmitting packet " to-send " on descriptor " current)
                   (with-rtl8168-access (nic)
                     ;; Copy packet to buffer.
                     (let ((address (+ (rtl8168-tx-bounce-virt nic)
                                       (* current (mezzano.supervisor::align-up +rtl8168-mtu+ 128)))))
                       (dotimes (i (min +rtl8168-mtu+
                                        (length to-send)))
                         (setf (sys.int::memref-unsigned-byte-8 address i) (aref to-send i))))
                     ;; Configure the descriptor.
                     (setf (rtl8168-tx-desc-flags nic current) (logior (ash (min +rtl8168-mtu+ (length to-send))
                                                                            +rtl8168-descriptor-Frame_Length+)
                                                                       (ash 1 +rtl8168-descriptor-OWN+)
                                                                       (if (eql current (1- +rtl8168-n-tx-descriptors+))
                                                                           (ash 1 +rtl8168-descriptor-EOR+)
                                                                           0)
                                                                       ;; This is the first & last segment.
                                                                       (ash 1 +rtl8168-descriptor-FS+)
                                                                       (ash 1 +rtl8168-descriptor-LS+))
                           (rtl8168-tx-desc-vlan nic current) 0)
                     ;; Notify the card.
                     (setf (rtl8168-reg/8 nic +rtl8168-register-TPPoll+) (ash 1 +rtl8168-TPPoll-NPQ+)))
                   ;; One used.
                   (incf (rtl8168-tx-used-count nic))
                   ;; Advance current.
                   (setf (rtl8168-tx-current nic) (rem (1+ current) +rtl8168-n-tx-descriptors+))))
              (simple-irq-unmask (rtl8168-irq-handler nic)))
        (nic:unregister-network-card nic))))
  
  (defun rtl8168-allocate-ring (name size)
  
negative.code:     (setf (values (rtl8168-rx-bounce-phys nic)
                    (rtl8168-rx-bounce-virt nic))
            (rtl8168-allocate-bounce "RX" +rtl8168-n-rx-descriptors+))
      (when (not (rtl8168-reset nic))
        (format t "RTL8168 reset failed?!~%"))
      (simple-irq-unmask (rtl8168-irq-handler nic)))
    (nic:register-network-card nic)
    t)
  